From 1c6090193dcea4e97ff844ffe2d8745fafd5b9e4 Mon Sep 17 00:00:00 2001 From: Tobias Tiederle Date: Wed, 12 Oct 2022 15:08:55 +0000 Subject: [PATCH 01/22] add support for icingadb as only icingaweb2 data backend --- application/controllers/HostController.php | 27 ++-- application/controllers/ServiceController.php | 6 +- library/Director/Backend.php | 151 ++++++++++++++++++ library/Director/MonitorBackend.php | 16 ++ library/Director/MonitorBackendIcingadb.php | 111 +++++++++++++ library/Director/MonitorBackendMonitoring.php | 110 +++++++++++++ .../ProvidedHook/Icingadb/HostActions.php | 77 +++++++++ .../ProvidedHook/Icingadb/IcingadbSupport.php | 10 ++ .../ProvidedHook/Icingadb/ServiceActions.php | 92 +++++++++++ .../Web/Controller/ActionController.php | 16 +- register-hooks.php | 3 + 11 files changed, 597 insertions(+), 22 deletions(-) create mode 100644 library/Director/Backend.php create mode 100644 library/Director/MonitorBackend.php create mode 100644 library/Director/MonitorBackendIcingadb.php create mode 100644 library/Director/MonitorBackendMonitoring.php create mode 100644 library/Director/ProvidedHook/Icingadb/HostActions.php create mode 100644 library/Director/ProvidedHook/Icingadb/IcingadbSupport.php create mode 100644 library/Director/ProvidedHook/Icingadb/ServiceActions.php diff --git a/application/controllers/HostController.php b/application/controllers/HostController.php index 51056990..a23da138 100644 --- a/application/controllers/HostController.php +++ b/application/controllers/HostController.php @@ -33,8 +33,8 @@ class HostController extends ObjectController { $host = $this->getHostObject(); $auth = $this->Auth(); - $mon = $this->monitoring(); - if ($this->isServiceAction() && $mon->canModifyService($host, $this->getParam('service'))) { + $backend = $this->backend(); + if ($this->isServiceAction() && $backend->authCanEditService($auth, $host, $this->getParam('service'))) { return; } if ($auth->hasPermission(Permission::MONITORING_SERVICES_RO) && $this->isServicesReadOnlyAction()) { @@ -43,7 +43,7 @@ class HostController extends ObjectController if ($auth->hasPermission(Permission::HOSTS)) { // faster return; } - if ($mon->canModifyHost($host)) { + if ($backend->authCanEditHost($host)) { return; } $this->assertPermission(Permission::HOSTS); // complain about default hosts permission @@ -564,13 +564,20 @@ class HostController extends ObjectController { $host = $this->object; try { - if ($host->isObject() && $host instanceof IcingaHost && $this->monitoring()->hasHost($host)) { - $this->actions()->add(Link::create($this->translate('Show'), 'monitoring/host/show', [ - 'host' => $host->getObjectName() - ], [ - 'class' => 'icon-globe critical', - 'data-base-target' => '_next' - ])); + $backend = $this->backend(); + if ($host instanceof IcingaHost + && $backend->isAvailable() + && $host->isObject() + && $backend->hasHost($host->getObjectName()) + ) { + $this->actions()->add($backend->getHostLink( + $this->translate('Show'), + $host->getObjectName(), + [ + 'class' => 'icon-globe critical', + 'data-base-target' => '_next' + ] + )); // Intentionally placed here, show it only for deployed Hosts $this->addOptionalInspectLink(); diff --git a/application/controllers/ServiceController.php b/application/controllers/ServiceController.php index a24b5050..5d2f3d1f 100644 --- a/application/controllers/ServiceController.php +++ b/application/controllers/ServiceController.php @@ -30,10 +30,8 @@ class ServiceController extends ObjectController protected function checkDirectorPermissions() { if ($this->hasPermission(Permission::MONITORING_SERVICES)) { - if ($this->host && $service = $this->object) { - if ($this->monitoring()->canModifyService($this->host, $service->getObjectName())) { - return; - } + if ($this->backend()->authCanEditService($this->Auth(), $this->getParam('host'), $this->getParam('name'))) { + return; } } $this->assertPermission('director/hosts'); diff --git a/library/Director/Backend.php b/library/Director/Backend.php new file mode 100644 index 00000000..8aac0fc4 --- /dev/null +++ b/library/Director/Backend.php @@ -0,0 +1,151 @@ +null will use either, preferring icingadb + */ + public function __construct($backend_name = null) + { + $app = Icinga::app(); + $modules = $app->getModuleManager(); + + $tried_loading = false; + if (is_null($backend_name) || ($backend_name == self::ICINGADB)) { + if (!$modules->hasLoaded(self::ICINGADB) && $app->isCli()) { + $modules->loadEnabledModules(); + $tried_loading = true; + } + + if ($modules->hasLoaded(self::ICINGADB)) { + $this->backend = new MonitorBackendIcingadb(); + } + } + + if (is_null($this->backend) + && (is_null($backend_name) || ($backend_name == self::MONITORING))) { + if (!$tried_loading && !$modules->hasLoaded(self::MONITORING) && $app->isCli()) { + $modules->loadEnabledModules(); + } + + if ($modules->hasLoaded(self::MONITORING)) { + $this->backend = new MonitorBackendMonitoring(); + } + } + } + + public function isAvailable() + { + return (($this->backend !== null) && ($this->backend->isAvailable())); + } + + public function hasHost($hostname) + { + return (($this->backend === null) || $this->backend->hasHost($hostname)); + } + + public function hasService($hostname, $service) + { + return (($this->backend === null) || $this->backend->hasService($hostname, $service)); + } + + public function authCanEditHost(Auth $auth, $hostname, $service) + { + if ($auth->hasPermission('director/monitoring/hosts')) { + $restriction = null; + foreach ($auth->getRestrictions('director/monitoring/rw-object-filter') as $restriction) { + if ($this->hasHostWithExtraFilter($hostname, Filter::fromQueryString($restriction))) { + return true; + } + } + if ($restriction === null) { + return $this->hasHost($hostname); + } + } + + return false; + } + + public function authCanEditService(Auth $auth, $hostname, $service) + { + if ($hostname === null || $service === null) { + // TODO: UUID support! + return false; + } + if ($auth->hasPermission('director/monitoring/services')) { + $restriction = null; + foreach ($auth->getRestrictions('director/monitoring/rw-object-filter') as $restriction) { + if ($this->hasServiceWithExtraFilter($hostname, $service, Filter::fromQueryString($restriction))) { + return true; + } + } + if ($restriction === null) { + return $this->hasService($hostname, $service); + } + } + + return false; + } + + public function hasHostWithExtraFilter($hostname, Filter $filter) + { + if ($this->backend === null) { + return false; + } + + return $this->backend->select()->from('hostStatus', [ + 'hostname' => 'host_name', + ])->where('host_name', $hostname)->applyFilter($filter)->fetchOne() === $hostname; + } + + public function hasServiceWithExtraFilter($hostname, $service, Filter $filter) + { + if ($this->backend === null) { + return false; + } + + return (array) $this + ->prepareServiceKeyColumnQuery($hostname, $service) + ->applyFilter($filter) + ->fetchRow() === [ + 'hostname' => $hostname, + 'service' => $service, + ]; + } + + public function getHostLink($title, $hostname, array $attributes = null) + { + if ($this->backend !== null) { + return $this->backend->getHostLink($title, $hostname, $attributes); + } + return null; + } + + public function getHostState($hostname) + { + if ($this->backend === null) { + return (object) [ + 'hostname' => $hostname, + 'state' => 'pending', + 'problem' => '0', + 'acknowledged' => '0', + 'in_downtime' => '0', + 'output' => null, + ]; + } else { + return $this->backend->getHostState($hostname); + } + } +} diff --git a/library/Director/MonitorBackend.php b/library/Director/MonitorBackend.php new file mode 100644 index 00000000..95c3f123 --- /dev/null +++ b/library/Director/MonitorBackend.php @@ -0,0 +1,16 @@ +getModuleManager(); + return $modules->hasLoaded('icingadb'); + } + + public function hasHost($hostname) + { + $query = Host::on($this->getDb()); + $query->filter(Filter::equal('host.name', $hostname)); + + $this->applyRestrictions($query); + + /** @var Host $host */ + $host = $query->first(); + + return ($host !== null); + } + + public function hasService($hostname, $service) + { + $query = Service::on($this->getDb()); + $query + ->filter(Filter::all( + Filter::equal('service.name', $service), + Filter::equal('host.name', $hostname) + )); + + $this->applyRestrictions($query); + + /** @var Service $service */ + $service = $query->first(); + + return ($service !== null); + } + + public function getHostLink($title, $hostname, array $attributes = null) + { + return Link::create( + $title, + 'icingadb/host', + ['name' => $hostname], + $attributes + ); + } + + public function getHostState($hostname) + { + $hostStates = [ + '0' => 'up', + '1' => 'down', + '2' => 'unreachable', + '99' => 'pending', + ]; + + $query = Host::on($this->getDb())->with(['state']); + $query + ->setResultSetClass(VolatileStateResults::class) + ->filter(Filter::equal('host.name', $hostname)); + + $this->applyRestrictions($query); + + /** @var Host $host */ + $host = $query->first(); + + $result = (object) [ + 'hostname' => $hostname, + 'state' => '99', + 'problem' => '0', + 'acknowledged' => '0', + 'in_downtime' => '0', + 'output' => null, + ]; + + if ($host !== null) { + // TODO: implement this for icingadb (function is unused atm) + /** + $query = $this->backend->select()->from('hostStatus', [ + 'hostname' => 'host_name', + 'state' => 'host_state', + 'problem' => 'host_problem', + 'acknowledged' => 'host_acknowledged', + 'in_downtime' => 'host_in_downtime', + 'output' => 'host_output', + ])->where('host_name', $hostname); + */ + } + + $result->state = $hostStates[$result->state]; + return $result; + } +} diff --git a/library/Director/MonitorBackendMonitoring.php b/library/Director/MonitorBackendMonitoring.php new file mode 100644 index 00000000..de91b8dd --- /dev/null +++ b/library/Director/MonitorBackendMonitoring.php @@ -0,0 +1,110 @@ +getModuleManager(); + if (!$modules->hasLoaded('monitoring') && $app->isCli()) { + $app->getModuleManager()->loadEnabledModules(); + } + + if ($modules->hasLoaded('monitoring')) { + $this->backend = MonitoringBackend::instance(); + } + } + + public function isAvailable() + { + return $this->backend !== null; + } + + public function hasHost($hostname) + { + if ($this->backend === null) { + return false; + } + + return $this->backend->select()->from('hostStatus', [ + 'hostname' => 'host_name', + ])->where('host_name', $hostname)->fetchOne() === $hostname; + } + + public function hasService($hostname, $service) + { + if ($this->backend === null) { + return false; + } + + return (array) $this->prepareServiceKeyColumnQuery($hostname, $service)->fetchRow() === [ + 'hostname' => $hostname, + 'service' => $service, + ]; + } + + public function getHostLink($title, $hostname, array $attributes = null) + { + return Link::create( + $title, + 'monitoring/host/show', + ['host' => $hostname], + $attributes + ); + } + + public function getHostState($hostname) + { + $hostStates = [ + '0' => 'up', + '1' => 'down', + '2' => 'unreachable', + '99' => 'pending', + ]; + + $query = $this->backend->select()->from('hostStatus', [ + 'hostname' => 'host_name', + 'state' => 'host_state', + 'problem' => 'host_problem', + 'acknowledged' => 'host_acknowledged', + 'in_downtime' => 'host_in_downtime', + 'output' => 'host_output', + ])->where('host_name', $hostname); + + $res = $query->fetchRow(); + if ($res === false) { + $res = (object) [ + 'hostname' => $hostname, + 'state' => '99', + 'problem' => '0', + 'acknowledged' => '0', + 'in_downtime' => '0', + 'output' => null, + ]; + } + + $res->state = $hostStates[$res->state]; + + return $res; + } + + protected function prepareServiceKeyColumnQuery($hostname, $service) + { + return $this->backend + ->select() + ->from('serviceStatus', [ + 'hostname' => 'host_name', + 'service' => 'service_description', + ]) + ->where('host_name', $hostname) + ->where('service_description', $service); + } +} diff --git a/library/Director/ProvidedHook/Icingadb/HostActions.php b/library/Director/ProvidedHook/Icingadb/HostActions.php new file mode 100644 index 00000000..8bcc8638 --- /dev/null +++ b/library/Director/ProvidedHook/Icingadb/HostActions.php @@ -0,0 +1,77 @@ +getThem($host); + } catch (Exception $e) { + return array(); + } + } + + protected function getThem(Host $host): array + { + $actions = array(); + $db = $this->db(); + if (! $db) { + return $actions; + } + $hostname = $host->name; + if (Util::hasPermission('director/inspect')) { + $actions[mt('director', 'Inspect')] = Url::fromPath( + 'director/inspect/object', + array('type' => 'host', 'plural' => 'hosts', 'name' => $hostname) + ); + } + + $allowEdit = false; + if (Util::hasPermission('director/hosts') && IcingaHost::exists($hostname, $db)) { + $allowEdit = true; + } + $auth = Auth::getInstance(); + if (Util::hasPermission('director/monitoring/hosts')) { + $backend = new Backend(Backend::ICINGADB); + if ($backend->isAvailable() && $backend->authCanEditHost($auth, $hostname)) { + $allowEdit = IcingaHost::exists($hostname, $db); + } + } + + if ($allowEdit) { + $label = mt('director', 'Modify'); + $actions[] = new Link( + $label, + Url::fromPath('director/host/edit', [ + 'name' => $hostname + ]) + ); + } + + return $actions; + } + + protected function db() + { + $resourceName = Config::module('director')->get('db', 'resource'); + if (! $resourceName) { + return false; + } + + return Db::fromResourceName($resourceName); + } +} diff --git a/library/Director/ProvidedHook/Icingadb/IcingadbSupport.php b/library/Director/ProvidedHook/Icingadb/IcingadbSupport.php new file mode 100644 index 00000000..5a593046 --- /dev/null +++ b/library/Director/ProvidedHook/Icingadb/IcingadbSupport.php @@ -0,0 +1,10 @@ +getThem($service); + } catch (Exception $e) { + die($e); + return []; + } + } + + /** + * @param Service $service + * @return array + * @throws \Icinga\Exception\ProgrammingError + */ + protected function getThem(Service $service) + { + $actions = []; + $db = $this->db(); + if (! $db) { + return []; + } + + $hostname = $service->host->name; + $serviceName = $service->name; + if (Util::hasPermission('director/inspect')) { + $actions[mt('director', 'Inspect')] = Url::fromPath('director/inspect/object', [ + 'type' => 'service', + 'plural' => 'services', + 'name' => sprintf( + '%s!%s', + $hostname, + $serviceName + ) + ]); + } + + $title = null; + if (Util::hasPermission('director/hosts')) { + $title = mt('director', 'Modify'); + } elseif (Util::hasPermission('director/monitoring/services')) { + $backend = new Backend(Backend::ICINGADB); + if ($backend->isAvailable() + && $backend->authCanEditService(Auth::getInstance(), $hostname, $serviceName) + ) { + $title = mt('director', 'Modify'); + } + } elseif (Util::hasPermission('director/monitoring/services-ro')) { + $title = mt('director', 'Configuration'); + } + + if ($title && IcingaHost::exists($hostname, $db)) { + $actions[] = new Link( + $title, + Url::fromPath('director/host/findservice', [ + 'name' => $hostname, + 'service' => $serviceName + ]) + ); + } + + return $actions; + } + + protected function db() + { + $resourceName = Config::module('director')->get('db', 'resource'); + if (! $resourceName) { + return false; + } + + return Db::fromResourceName($resourceName); + } +} diff --git a/library/Director/Web/Controller/ActionController.php b/library/Director/Web/Controller/ActionController.php index a281e170..1740f849 100644 --- a/library/Director/Web/Controller/ActionController.php +++ b/library/Director/Web/Controller/ActionController.php @@ -7,7 +7,7 @@ use Icinga\Application\Benchmark; use Icinga\Data\Paginatable; use Icinga\Exception\NotFoundError; use Icinga\Exception\ProgrammingError; -use Icinga\Module\Director\Integration\MonitoringModule\Monitoring; +use Icinga\Module\Director\Backend; use Icinga\Module\Director\Web\Controller\Extension\CoreApi; use Icinga\Module\Director\Web\Controller\Extension\DirectorDb; use Icinga\Module\Director\Web\Controller\Extension\RestApi; @@ -36,8 +36,8 @@ abstract class ActionController extends Controller implements ControlsAndContent /** @var UrlParams Hint for IDE, somehow does not work in web */ protected $params; - /** @var Monitoring */ - private $monitoring; + /** @var Backend */ + private $backend; /** * @throws SecurityException @@ -240,14 +240,14 @@ abstract class ActionController extends Controller implements ControlsAndContent } /** - * @return Monitoring + * @return Backend */ - protected function monitoring() + protected function backend() { - if ($this->monitoring === null) { - $this->monitoring = new Monitoring($this->Auth()); + if ($this->backend === null) { + $this->backend = new Backend(); } - return $this->monitoring; + return $this->backend; } } diff --git a/register-hooks.php b/register-hooks.php index 62fd5f51..36e7e701 100644 --- a/register-hooks.php +++ b/register-hooks.php @@ -66,6 +66,9 @@ use Icinga\Module\Director\ProvidedHook\IcingaDbCubeLinks; if ($this->getConfig()->get('frontend', 'disabled', 'no') !== 'yes') { $this->provideHook('monitoring/HostActions'); $this->provideHook('monitoring/ServiceActions'); + $this->provideHook('icingadb/HostActions'); + $this->provideHook('icingadb/ServiceActions'); + $this->provideHook('icingadb/icingadbSupport'); $this->provideHook('cube/Actions', CubeLinks::class); $this->provideHook('cube/IcingaDbActions', IcingaDbCubeLinks::class); } From b28b36f815d503017587359ad07948c18844a4b9 Mon Sep 17 00:00:00 2001 From: Tobias Tiederle Date: Thu, 29 Dec 2022 19:36:25 +0000 Subject: [PATCH 02/22] move classes into subfolder fix some problems and mark TODO --- library/Director/Backend.php | 48 +++++++------------ .../Director/{ => Backend}/MonitorBackend.php | 8 +++- .../{ => Backend}/MonitorBackendIcingadb.php | 15 +++++- .../MonitorBackendMonitoring.php | 29 ++++++++++- 4 files changed, 67 insertions(+), 33 deletions(-) rename library/Director/{ => Backend}/MonitorBackend.php (55%) rename library/Director/{ => Backend}/MonitorBackendIcingadb.php (89%) rename library/Director/{ => Backend}/MonitorBackendMonitoring.php (77%) diff --git a/library/Director/Backend.php b/library/Director/Backend.php index 8aac0fc4..ec1dc662 100644 --- a/library/Director/Backend.php +++ b/library/Director/Backend.php @@ -5,6 +5,9 @@ namespace Icinga\Module\Director; use Icinga\Application\Icinga; use Icinga\Authentication\Auth; use Icinga\Data\Filter\Filter; +use Icinga\Module\Director\Backend\MonitorBackend; +use Icinga\Module\Director\Backend\MonitorBackendIcingadb; +use Icinga\Module\Director\Backend\MonitorBackendMonitoring; class Backend implements MonitorBackend { @@ -53,15 +56,26 @@ class Backend implements MonitorBackend public function hasHost($hostname) { - return (($this->backend === null) || $this->backend->hasHost($hostname)); + return (($this->backend !== null) && $this->backend->hasHost($hostname)); + } + + public function hasHostWithExtraFilter($hostname, Filter $filter) + { + return (($this->backend !== null) && $this->backend->hasHostWithExtraFilter($hostname, $filter)); } public function hasService($hostname, $service) { - return (($this->backend === null) || $this->backend->hasService($hostname, $service)); + return (($this->backend !== null) && $this->backend->hasService($hostname, $service)); } - public function authCanEditHost(Auth $auth, $hostname, $service) + public function hasServiceWithExtraFilter($hostname, $service, Filter $filter) + { + return (($this->backend !== null) + && $this->backend->hasServiceWithExtraFilter($hostname, $service, $filter)); + } + + public function authCanEditHost(Auth $auth, $hostname) { if ($auth->hasPermission('director/monitoring/hosts')) { $restriction = null; @@ -99,32 +113,6 @@ class Backend implements MonitorBackend return false; } - public function hasHostWithExtraFilter($hostname, Filter $filter) - { - if ($this->backend === null) { - return false; - } - - return $this->backend->select()->from('hostStatus', [ - 'hostname' => 'host_name', - ])->where('host_name', $hostname)->applyFilter($filter)->fetchOne() === $hostname; - } - - public function hasServiceWithExtraFilter($hostname, $service, Filter $filter) - { - if ($this->backend === null) { - return false; - } - - return (array) $this - ->prepareServiceKeyColumnQuery($hostname, $service) - ->applyFilter($filter) - ->fetchRow() === [ - 'hostname' => $hostname, - 'service' => $service, - ]; - } - public function getHostLink($title, $hostname, array $attributes = null) { if ($this->backend !== null) { @@ -138,7 +126,7 @@ class Backend implements MonitorBackend if ($this->backend === null) { return (object) [ 'hostname' => $hostname, - 'state' => 'pending', + 'state' => '99', 'problem' => '0', 'acknowledged' => '0', 'in_downtime' => '0', diff --git a/library/Director/MonitorBackend.php b/library/Director/Backend/MonitorBackend.php similarity index 55% rename from library/Director/MonitorBackend.php rename to library/Director/Backend/MonitorBackend.php index 95c3f123..6356ed83 100644 --- a/library/Director/MonitorBackend.php +++ b/library/Director/Backend/MonitorBackend.php @@ -1,6 +1,8 @@ getDb()); @@ -53,6 +60,12 @@ class MonitorBackendIcingadb implements MonitorBackend return ($service !== null); } + public function hasServiceWithExtraFilter($hostname, $service, DataFilter $filter) + { + // TODO + return false; + } + public function getHostLink($title, $hostname, array $attributes = null) { return Link::create( diff --git a/library/Director/MonitorBackendMonitoring.php b/library/Director/Backend/MonitorBackendMonitoring.php similarity index 77% rename from library/Director/MonitorBackendMonitoring.php rename to library/Director/Backend/MonitorBackendMonitoring.php index de91b8dd..a9174e71 100644 --- a/library/Director/MonitorBackendMonitoring.php +++ b/library/Director/Backend/MonitorBackendMonitoring.php @@ -1,9 +1,10 @@ where('host_name', $hostname)->fetchOne() === $hostname; } + public function hasHostWithExtraFilter($hostname, Filter $filter) + { + if ($this->backend === null) { + return false; + } + + return $this->backend->select()->from('hostStatus', [ + 'hostname' => 'host_name', + ])->where('host_name', $hostname)->applyFilter($filter)->fetchOne() === $hostname; + } + public function hasService($hostname, $service) { if ($this->backend === null) { @@ -51,6 +63,21 @@ class MonitorBackendMonitoring implements MonitorBackend ]; } + public function hasServiceWithExtraFilter($hostname, $service, Filter $filter) + { + if ($this->backend === null) { + return false; + } + + return (array) $this + ->prepareServiceKeyColumnQuery($hostname, $service) + ->applyFilter($filter) + ->fetchRow() === [ + 'hostname' => $hostname, + 'service' => $service, + ]; + } + public function getHostLink($title, $hostname, array $attributes = null) { return Link::create( From 89134e0366c9b9c0d733033c8e78068949425eb0 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Fri, 17 Nov 2023 10:27:25 +0100 Subject: [PATCH 03/22] Remove obsolate class `Backend` and its usages - Create the backend directly in ActionController::backend() - Simplify the code --- library/Director/Backend.php | 139 ------------------ library/Director/Backend/MonitorBackend.php | 4 + .../Backend/MonitorBackendIcingadb.php | 12 ++ .../Backend/MonitorBackendMonitoring.php | 12 ++ .../ProvidedHook/Icingadb/HostActions.php | 8 +- .../ProvidedHook/Icingadb/ServiceActions.php | 7 +- .../Web/Controller/ActionController.php | 16 +- 7 files changed, 46 insertions(+), 152 deletions(-) delete mode 100644 library/Director/Backend.php diff --git a/library/Director/Backend.php b/library/Director/Backend.php deleted file mode 100644 index ec1dc662..00000000 --- a/library/Director/Backend.php +++ /dev/null @@ -1,139 +0,0 @@ -null will use either, preferring icingadb - */ - public function __construct($backend_name = null) - { - $app = Icinga::app(); - $modules = $app->getModuleManager(); - - $tried_loading = false; - if (is_null($backend_name) || ($backend_name == self::ICINGADB)) { - if (!$modules->hasLoaded(self::ICINGADB) && $app->isCli()) { - $modules->loadEnabledModules(); - $tried_loading = true; - } - - if ($modules->hasLoaded(self::ICINGADB)) { - $this->backend = new MonitorBackendIcingadb(); - } - } - - if (is_null($this->backend) - && (is_null($backend_name) || ($backend_name == self::MONITORING))) { - if (!$tried_loading && !$modules->hasLoaded(self::MONITORING) && $app->isCli()) { - $modules->loadEnabledModules(); - } - - if ($modules->hasLoaded(self::MONITORING)) { - $this->backend = new MonitorBackendMonitoring(); - } - } - } - - public function isAvailable() - { - return (($this->backend !== null) && ($this->backend->isAvailable())); - } - - public function hasHost($hostname) - { - return (($this->backend !== null) && $this->backend->hasHost($hostname)); - } - - public function hasHostWithExtraFilter($hostname, Filter $filter) - { - return (($this->backend !== null) && $this->backend->hasHostWithExtraFilter($hostname, $filter)); - } - - public function hasService($hostname, $service) - { - return (($this->backend !== null) && $this->backend->hasService($hostname, $service)); - } - - public function hasServiceWithExtraFilter($hostname, $service, Filter $filter) - { - return (($this->backend !== null) - && $this->backend->hasServiceWithExtraFilter($hostname, $service, $filter)); - } - - public function authCanEditHost(Auth $auth, $hostname) - { - if ($auth->hasPermission('director/monitoring/hosts')) { - $restriction = null; - foreach ($auth->getRestrictions('director/monitoring/rw-object-filter') as $restriction) { - if ($this->hasHostWithExtraFilter($hostname, Filter::fromQueryString($restriction))) { - return true; - } - } - if ($restriction === null) { - return $this->hasHost($hostname); - } - } - - return false; - } - - public function authCanEditService(Auth $auth, $hostname, $service) - { - if ($hostname === null || $service === null) { - // TODO: UUID support! - return false; - } - if ($auth->hasPermission('director/monitoring/services')) { - $restriction = null; - foreach ($auth->getRestrictions('director/monitoring/rw-object-filter') as $restriction) { - if ($this->hasServiceWithExtraFilter($hostname, $service, Filter::fromQueryString($restriction))) { - return true; - } - } - if ($restriction === null) { - return $this->hasService($hostname, $service); - } - } - - return false; - } - - public function getHostLink($title, $hostname, array $attributes = null) - { - if ($this->backend !== null) { - return $this->backend->getHostLink($title, $hostname, $attributes); - } - return null; - } - - public function getHostState($hostname) - { - if ($this->backend === null) { - return (object) [ - 'hostname' => $hostname, - 'state' => '99', - 'problem' => '0', - 'acknowledged' => '0', - 'in_downtime' => '0', - 'output' => null, - ]; - } else { - return $this->backend->getHostState($hostname); - } - } -} diff --git a/library/Director/Backend/MonitorBackend.php b/library/Director/Backend/MonitorBackend.php index 6356ed83..da41fd2f 100644 --- a/library/Director/Backend/MonitorBackend.php +++ b/library/Director/Backend/MonitorBackend.php @@ -19,4 +19,8 @@ interface MonitorBackend public function getHostLink($title, $hostname, array $attributes = null); public function getHostState($hostname); + + public function canModifyHost(string $hostName): bool; + + public function canModifyService(string $hostName, string $serviceName): bool; } diff --git a/library/Director/Backend/MonitorBackendIcingadb.php b/library/Director/Backend/MonitorBackendIcingadb.php index 7893e14b..a1cea3e0 100644 --- a/library/Director/Backend/MonitorBackendIcingadb.php +++ b/library/Director/Backend/MonitorBackendIcingadb.php @@ -121,4 +121,16 @@ class MonitorBackendIcingadb implements MonitorBackend $result->state = $hostStates[$result->state]; return $result; } + + public function canModifyHost(string $hostName): bool + { + // TODO: Implement canModifyService() method. + return false; + } + + public function canModifyService(string $hostName, string $serviceName): bool + { + // TODO: Implement canModifyService() method. + return false; + } } diff --git a/library/Director/Backend/MonitorBackendMonitoring.php b/library/Director/Backend/MonitorBackendMonitoring.php index a9174e71..0f2fdf71 100644 --- a/library/Director/Backend/MonitorBackendMonitoring.php +++ b/library/Director/Backend/MonitorBackendMonitoring.php @@ -134,4 +134,16 @@ class MonitorBackendMonitoring implements MonitorBackend ->where('host_name', $hostname) ->where('service_description', $service); } + + public function canModifyHost(string $hostName): bool + { + // TODO: Implement canModifyHost() method. + return false; + } + + public function canModifyService(string $hostName, string $serviceName): bool + { + // TODO: Implement canModifyService() method. + return false; + } } diff --git a/library/Director/ProvidedHook/Icingadb/HostActions.php b/library/Director/ProvidedHook/Icingadb/HostActions.php index 8bcc8638..b3902874 100644 --- a/library/Director/ProvidedHook/Icingadb/HostActions.php +++ b/library/Director/ProvidedHook/Icingadb/HostActions.php @@ -4,9 +4,8 @@ namespace Icinga\Module\Director\ProvidedHook\Icingadb; use Exception; use Icinga\Application\Config; -use Icinga\Authentication\Auth; +use Icinga\Module\Director\Backend\MonitorBackendIcingadb; use Icinga\Module\Director\Db; -use Icinga\Module\Director\Backend; use Icinga\Module\Director\Objects\IcingaHost; use Icinga\Module\Director\Util; use Icinga\Module\Icingadb\Hook\HostActionsHook; @@ -44,10 +43,9 @@ class HostActions extends HostActionsHook if (Util::hasPermission('director/hosts') && IcingaHost::exists($hostname, $db)) { $allowEdit = true; } - $auth = Auth::getInstance(); if (Util::hasPermission('director/monitoring/hosts')) { - $backend = new Backend(Backend::ICINGADB); - if ($backend->isAvailable() && $backend->authCanEditHost($auth, $hostname)) { + $backend = new MonitorBackendIcingadb(); + if ($backend->isAvailable() && $backend->canModifyHost($hostname)) { $allowEdit = IcingaHost::exists($hostname, $db); } } diff --git a/library/Director/ProvidedHook/Icingadb/ServiceActions.php b/library/Director/ProvidedHook/Icingadb/ServiceActions.php index f3ca4b5b..383d915d 100644 --- a/library/Director/ProvidedHook/Icingadb/ServiceActions.php +++ b/library/Director/ProvidedHook/Icingadb/ServiceActions.php @@ -4,9 +4,8 @@ namespace Icinga\Module\Director\ProvidedHook\Icingadb; use Exception; use Icinga\Application\Config; -use Icinga\Authentication\Auth; +use Icinga\Module\Director\Backend\MonitorBackendIcingadb; use Icinga\Module\Director\Db; -use Icinga\Module\Director\Backend; use Icinga\Module\Director\Objects\IcingaHost; use Icinga\Module\Director\Util; use Icinga\Module\Icingadb\Hook\ServiceActionsHook; @@ -57,9 +56,9 @@ class ServiceActions extends ServiceActionsHook if (Util::hasPermission('director/hosts')) { $title = mt('director', 'Modify'); } elseif (Util::hasPermission('director/monitoring/services')) { - $backend = new Backend(Backend::ICINGADB); + $backend = new MonitorBackendIcingadb(); if ($backend->isAvailable() - && $backend->authCanEditService(Auth::getInstance(), $hostname, $serviceName) + && $backend->canModifyService($hostname, $serviceName) ) { $title = mt('director', 'Modify'); } diff --git a/library/Director/Web/Controller/ActionController.php b/library/Director/Web/Controller/ActionController.php index 1740f849..b58a955f 100644 --- a/library/Director/Web/Controller/ActionController.php +++ b/library/Director/Web/Controller/ActionController.php @@ -4,10 +4,14 @@ namespace Icinga\Module\Director\Web\Controller; use gipfl\Translation\StaticTranslator; use Icinga\Application\Benchmark; +use Icinga\Application\Icinga; +use Icinga\Application\Modules\Module; use Icinga\Data\Paginatable; use Icinga\Exception\NotFoundError; use Icinga\Exception\ProgrammingError; -use Icinga\Module\Director\Backend; +use Icinga\Module\Director\Backend\MonitorBackend; +use Icinga\Module\Director\Backend\MonitorBackendIcingadb; +use Icinga\Module\Director\Backend\MonitorBackendMonitoring; use Icinga\Module\Director\Web\Controller\Extension\CoreApi; use Icinga\Module\Director\Web\Controller\Extension\DirectorDb; use Icinga\Module\Director\Web\Controller\Extension\RestApi; @@ -36,7 +40,7 @@ abstract class ActionController extends Controller implements ControlsAndContent /** @var UrlParams Hint for IDE, somehow does not work in web */ protected $params; - /** @var Backend */ + /** @var MonitorBackend */ private $backend; /** @@ -240,12 +244,16 @@ abstract class ActionController extends Controller implements ControlsAndContent } /** - * @return Backend + * @return MonitorBackend */ protected function backend() { if ($this->backend === null) { - $this->backend = new Backend(); + if (Module::exists('icingadb')) { + $this->backend = new MonitorBackendIcingadb(); + } else { + $this->backend = new MonitorBackendMonitoring(); + } } return $this->backend; From 9baa3c4341e6ebed0b03230e7a20906d462783d8 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Fri, 17 Nov 2023 12:31:20 +0100 Subject: [PATCH 04/22] Remove redudant class `MonitorBackendMonitoring` and adjuct code accordigly - Use class `Monitoring` instead - Remove not in use methods from `MonitorBackend` interface and from classes that implements this interface - Add param types and return type hint to methods --- application/controllers/HostController.php | 19 +-- application/controllers/ServiceController.php | 2 +- library/Director/Backend/MonitorBackend.php | 18 +-- .../Backend/MonitorBackendIcingadb.php | 75 +-------- .../Backend/MonitorBackendMonitoring.php | 149 ------------------ .../DirectorObject/Lookup/ServiceFinder.php | 2 +- .../MonitoringModule/Monitoring.php | 61 +++---- .../ProvidedHook/Monitoring/HostActions.php | 2 +- .../Monitoring/ServiceActions.php | 2 +- .../Web/Controller/ActionController.php | 4 +- 10 files changed, 49 insertions(+), 285 deletions(-) delete mode 100644 library/Director/Backend/MonitorBackendMonitoring.php diff --git a/application/controllers/HostController.php b/application/controllers/HostController.php index a23da138..cce491e2 100644 --- a/application/controllers/HostController.php +++ b/application/controllers/HostController.php @@ -34,7 +34,9 @@ class HostController extends ObjectController $host = $this->getHostObject(); $auth = $this->Auth(); $backend = $this->backend(); - if ($this->isServiceAction() && $backend->authCanEditService($auth, $host, $this->getParam('service'))) { + if ($this->isServiceAction() + && $backend->canModifyService($host->getObjectName(), $this->getParam('service')) + ) { return; } if ($auth->hasPermission(Permission::MONITORING_SERVICES_RO) && $this->isServicesReadOnlyAction()) { @@ -43,7 +45,7 @@ class HostController extends ObjectController if ($auth->hasPermission(Permission::HOSTS)) { // faster return; } - if ($backend->authCanEditHost($host)) { + if ($backend->canModifyHost($host->getObjectName())) { return; } $this->assertPermission(Permission::HOSTS); // complain about default hosts permission @@ -570,14 +572,13 @@ class HostController extends ObjectController && $host->isObject() && $backend->hasHost($host->getObjectName()) ) { - $this->actions()->add($backend->getHostLink( - $this->translate('Show'), - $host->getObjectName(), + $this->actions()->add(Link::create($this->translate('Show'), + $backend->getHostUrl($host->getObjectName()), + null, [ - 'class' => 'icon-globe critical', - 'data-base-target' => '_next' - ] - )); + 'class' => 'icon-globe critical', + 'data-base-target' => '_next' + ])); // Intentionally placed here, show it only for deployed Hosts $this->addOptionalInspectLink(); diff --git a/application/controllers/ServiceController.php b/application/controllers/ServiceController.php index 5d2f3d1f..c09b0937 100644 --- a/application/controllers/ServiceController.php +++ b/application/controllers/ServiceController.php @@ -30,7 +30,7 @@ class ServiceController extends ObjectController protected function checkDirectorPermissions() { if ($this->hasPermission(Permission::MONITORING_SERVICES)) { - if ($this->backend()->authCanEditService($this->Auth(), $this->getParam('host'), $this->getParam('name'))) { + if ($this->backend()->canModifyService($this->getParam('host'), $this->getParam('name'))) { return; } } diff --git a/library/Director/Backend/MonitorBackend.php b/library/Director/Backend/MonitorBackend.php index da41fd2f..5950d2c0 100644 --- a/library/Director/Backend/MonitorBackend.php +++ b/library/Director/Backend/MonitorBackend.php @@ -2,25 +2,19 @@ namespace Icinga\Module\Director\Backend; -use Icinga\Data\Filter\Filter; +use Icinga\Web\Url; interface MonitorBackend { - public function isAvailable(); + public function isAvailable(): bool; - public function hasHost($hostname); + public function hasHost(string $hostname): bool; - public function hasHostWithExtraFilter($hostname, Filter $filter); - - public function hasService($hostname, $service); - - public function hasServiceWithExtraFilter($hostname, $service, Filter $filter); - - public function getHostLink($title, $hostname, array $attributes = null); - - public function getHostState($hostname); + public function hasService(string $hostname, string $service): bool; public function canModifyHost(string $hostName): bool; public function canModifyService(string $hostName, string $serviceName): bool; + + public function getHostUrl(string $hostname): Url; } diff --git a/library/Director/Backend/MonitorBackendIcingadb.php b/library/Director/Backend/MonitorBackendIcingadb.php index a1cea3e0..2305f696 100644 --- a/library/Director/Backend/MonitorBackendIcingadb.php +++ b/library/Director/Backend/MonitorBackendIcingadb.php @@ -5,11 +5,13 @@ namespace Icinga\Module\Director\Backend; use gipfl\IcingaWeb2\Link; use Icinga\Application\Icinga; use Icinga\Data\Filter\Filter as DataFilter; +use Icinga\Module\Director\Objects\IcingaHost; use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Common\Database; use Icinga\Module\Icingadb\Model\Host; use Icinga\Module\Icingadb\Model\Service; use Icinga\Module\Icingadb\Redis\VolatileStateResults; +use Icinga\Web\Url; use ipl\Stdlib\Filter; class MonitorBackendIcingadb implements MonitorBackend @@ -17,14 +19,14 @@ class MonitorBackendIcingadb implements MonitorBackend use Database; use Auth; - public function isAvailable() + public function isAvailable(): bool { $app = Icinga::app(); $modules = $app->getModuleManager(); return $modules->hasLoaded('icingadb'); } - public function hasHost($hostname) + public function hasHost($hostname): bool { $query = Host::on($this->getDb()); $query->filter(Filter::equal('host.name', $hostname)); @@ -37,13 +39,7 @@ class MonitorBackendIcingadb implements MonitorBackend return ($host !== null); } - public function hasHostWithExtraFilter($hostname, DataFilter $filter) - { - // TODO - return false; - } - - public function hasService($hostname, $service) + public function hasService($hostname, $service): bool { $query = Service::on($this->getDb()); $query @@ -60,66 +56,9 @@ class MonitorBackendIcingadb implements MonitorBackend return ($service !== null); } - public function hasServiceWithExtraFilter($hostname, $service, DataFilter $filter) + public function getHostUrl(string $hostname): Url { - // TODO - return false; - } - - public function getHostLink($title, $hostname, array $attributes = null) - { - return Link::create( - $title, - 'icingadb/host', - ['name' => $hostname], - $attributes - ); - } - - public function getHostState($hostname) - { - $hostStates = [ - '0' => 'up', - '1' => 'down', - '2' => 'unreachable', - '99' => 'pending', - ]; - - $query = Host::on($this->getDb())->with(['state']); - $query - ->setResultSetClass(VolatileStateResults::class) - ->filter(Filter::equal('host.name', $hostname)); - - $this->applyRestrictions($query); - - /** @var Host $host */ - $host = $query->first(); - - $result = (object) [ - 'hostname' => $hostname, - 'state' => '99', - 'problem' => '0', - 'acknowledged' => '0', - 'in_downtime' => '0', - 'output' => null, - ]; - - if ($host !== null) { - // TODO: implement this for icingadb (function is unused atm) - /** - $query = $this->backend->select()->from('hostStatus', [ - 'hostname' => 'host_name', - 'state' => 'host_state', - 'problem' => 'host_problem', - 'acknowledged' => 'host_acknowledged', - 'in_downtime' => 'host_in_downtime', - 'output' => 'host_output', - ])->where('host_name', $hostname); - */ - } - - $result->state = $hostStates[$result->state]; - return $result; + return Url::fromPath('icingadb/host', ['name' => $hostname]); } public function canModifyHost(string $hostName): bool diff --git a/library/Director/Backend/MonitorBackendMonitoring.php b/library/Director/Backend/MonitorBackendMonitoring.php deleted file mode 100644 index 0f2fdf71..00000000 --- a/library/Director/Backend/MonitorBackendMonitoring.php +++ /dev/null @@ -1,149 +0,0 @@ -getModuleManager(); - if (!$modules->hasLoaded('monitoring') && $app->isCli()) { - $app->getModuleManager()->loadEnabledModules(); - } - - if ($modules->hasLoaded('monitoring')) { - $this->backend = MonitoringBackend::instance(); - } - } - - public function isAvailable() - { - return $this->backend !== null; - } - - public function hasHost($hostname) - { - if ($this->backend === null) { - return false; - } - - return $this->backend->select()->from('hostStatus', [ - 'hostname' => 'host_name', - ])->where('host_name', $hostname)->fetchOne() === $hostname; - } - - public function hasHostWithExtraFilter($hostname, Filter $filter) - { - if ($this->backend === null) { - return false; - } - - return $this->backend->select()->from('hostStatus', [ - 'hostname' => 'host_name', - ])->where('host_name', $hostname)->applyFilter($filter)->fetchOne() === $hostname; - } - - public function hasService($hostname, $service) - { - if ($this->backend === null) { - return false; - } - - return (array) $this->prepareServiceKeyColumnQuery($hostname, $service)->fetchRow() === [ - 'hostname' => $hostname, - 'service' => $service, - ]; - } - - public function hasServiceWithExtraFilter($hostname, $service, Filter $filter) - { - if ($this->backend === null) { - return false; - } - - return (array) $this - ->prepareServiceKeyColumnQuery($hostname, $service) - ->applyFilter($filter) - ->fetchRow() === [ - 'hostname' => $hostname, - 'service' => $service, - ]; - } - - public function getHostLink($title, $hostname, array $attributes = null) - { - return Link::create( - $title, - 'monitoring/host/show', - ['host' => $hostname], - $attributes - ); - } - - public function getHostState($hostname) - { - $hostStates = [ - '0' => 'up', - '1' => 'down', - '2' => 'unreachable', - '99' => 'pending', - ]; - - $query = $this->backend->select()->from('hostStatus', [ - 'hostname' => 'host_name', - 'state' => 'host_state', - 'problem' => 'host_problem', - 'acknowledged' => 'host_acknowledged', - 'in_downtime' => 'host_in_downtime', - 'output' => 'host_output', - ])->where('host_name', $hostname); - - $res = $query->fetchRow(); - if ($res === false) { - $res = (object) [ - 'hostname' => $hostname, - 'state' => '99', - 'problem' => '0', - 'acknowledged' => '0', - 'in_downtime' => '0', - 'output' => null, - ]; - } - - $res->state = $hostStates[$res->state]; - - return $res; - } - - protected function prepareServiceKeyColumnQuery($hostname, $service) - { - return $this->backend - ->select() - ->from('serviceStatus', [ - 'hostname' => 'host_name', - 'service' => 'service_description', - ]) - ->where('host_name', $hostname) - ->where('service_description', $service); - } - - public function canModifyHost(string $hostName): bool - { - // TODO: Implement canModifyHost() method. - return false; - } - - public function canModifyService(string $hostName, string $serviceName): bool - { - // TODO: Implement canModifyService() method. - return false; - } -} diff --git a/library/Director/DirectorObject/Lookup/ServiceFinder.php b/library/Director/DirectorObject/Lookup/ServiceFinder.php index 583b4d35..fba6b65e 100644 --- a/library/Director/DirectorObject/Lookup/ServiceFinder.php +++ b/library/Director/DirectorObject/Lookup/ServiceFinder.php @@ -68,7 +68,7 @@ class ServiceFinder } if ($this->auth->hasPermission(Permission::MONITORING_HOSTS)) { if ($info = $this::find($this->host, $serviceName)) { - if ((new Monitoring($this->auth))->canModifyServiceByName($this->host->getObjectName(), $serviceName)) { + if ((new Monitoring($this->auth))->canModifyService($this->host->getObjectName(), $serviceName)) { return $info->getUrl(); } } diff --git a/library/Director/Integration/MonitoringModule/Monitoring.php b/library/Director/Integration/MonitoringModule/Monitoring.php index 3a9cb296..2cda38b1 100644 --- a/library/Director/Integration/MonitoringModule/Monitoring.php +++ b/library/Director/Integration/MonitoringModule/Monitoring.php @@ -10,10 +10,11 @@ use Icinga\Exception\ConfigurationError; use Icinga\Module\Director\Auth\MonitoringRestriction; use Icinga\Module\Director\Auth\Permission; use Icinga\Module\Director\Auth\Restriction; -use Icinga\Module\Director\Objects\IcingaHost; +use Icinga\Module\Director\Backend\MonitorBackend; use Icinga\Module\Monitoring\Backend\MonitoringBackend; +use Icinga\Web\Url; -class Monitoring +class Monitoring implements MonitorBackend { /** @var ?MonitoringBackend */ protected $backend; @@ -32,9 +33,14 @@ class Monitoring return $this->backend !== null; } - public function hasHost(IcingaHost $host): bool + public function getHostUrl(string $hostname): Url { - return $this->hasHostByName($host->getObjectName()); + return Url::fromPath('monitoring/host/show', ['host' => $hostname]); + } + + public function hasHost($hostname): bool + { + return $this->hasHostByName($hostname); } public function hasHostByName($hostname): bool @@ -50,6 +56,12 @@ class Monitoring } } + + public function hasService($hostname, $service): bool + { + return $this->hasServiceByName($hostname, $service); + } + public function hasServiceByName($hostname, $service): bool { if (! $this->isAvailable()) { @@ -63,9 +75,9 @@ class Monitoring } } - public function canModifyService(IcingaHost $host, $service): bool + public function canModifyService(string $hostName, string $serviceName): bool { - return $this->canModifyServiceByName($host->getObjectName(), $service); + return $this->canModifyServiceByName($hostName, $serviceName); } public function canModifyServiceByName($hostname, $service): bool @@ -88,9 +100,9 @@ class Monitoring return false; } - public function canModifyHost(IcingaHost $host): bool + public function canModifyHost(string $hostName): bool { - return $this->canModifyHostByName($host->getObjectName()); + return $this->canModifyHostByName($hostName); } public function canModifyHostByName($hostname): bool @@ -132,39 +144,6 @@ class Monitoring } } - public function getHostState($hostname) - { - $hostStates = [ - '0' => 'up', - '1' => 'down', - '2' => 'unreachable', - '99' => 'pending', - ]; - - $query = $this->selectHostStatus($hostname, [ - 'hostname' => 'host_name', - 'state' => 'host_state', - 'problem' => 'host_problem', - 'acknowledged' => 'host_acknowledged', - 'in_downtime' => 'host_in_downtime', - ])->where('host_name', $hostname); - - $res = $query->fetchRow(); - if ($res === false) { - $res = (object) [ - 'hostname' => $hostname, - 'state' => '99', - 'problem' => '0', - 'acknowledged' => '0', - 'in_downtime' => '0', - ]; - } - - $res->state = $hostStates[$res->state]; - - return $res; - } - protected function selectHost($hostname) { return $this->selectHostStatus($hostname, [ diff --git a/library/Director/ProvidedHook/Monitoring/HostActions.php b/library/Director/ProvidedHook/Monitoring/HostActions.php index d1379c8a..2d0469de 100644 --- a/library/Director/ProvidedHook/Monitoring/HostActions.php +++ b/library/Director/ProvidedHook/Monitoring/HostActions.php @@ -45,7 +45,7 @@ class HostActions extends HostActionsHook $allowEdit = true; } if (Util::hasPermission(Permission::MONITORING_HOSTS)) { - if ((new Monitoring(Auth::getInstance()))->canModifyHostByName($hostname)) { + if ((new Monitoring(Auth::getInstance()))->canModifyHost($hostname)) { $allowEdit = IcingaHost::exists($hostname, $db); } } diff --git a/library/Director/ProvidedHook/Monitoring/ServiceActions.php b/library/Director/ProvidedHook/Monitoring/ServiceActions.php index 5796fde0..834b1664 100644 --- a/library/Director/ProvidedHook/Monitoring/ServiceActions.php +++ b/library/Director/ProvidedHook/Monitoring/ServiceActions.php @@ -56,7 +56,7 @@ class ServiceActions extends ServiceActionsHook if (Util::hasPermission(Permission::HOSTS)) { $title = mt('director', 'Modify'); } elseif (Util::hasPermission(Permission::MONITORING_SERVICES)) { - if ((new Monitoring(Auth::getInstance()))->canModifyServiceByName($hostname, $serviceName)) { + if ((new Monitoring(Auth::getInstance()))->canModifyService($hostname, $serviceName)) { $title = mt('director', 'Modify'); } } elseif (Util::hasPermission(Permission::MONITORING_SERVICES_RO)) { diff --git a/library/Director/Web/Controller/ActionController.php b/library/Director/Web/Controller/ActionController.php index b58a955f..b1aadb96 100644 --- a/library/Director/Web/Controller/ActionController.php +++ b/library/Director/Web/Controller/ActionController.php @@ -11,7 +11,7 @@ use Icinga\Exception\NotFoundError; use Icinga\Exception\ProgrammingError; use Icinga\Module\Director\Backend\MonitorBackend; use Icinga\Module\Director\Backend\MonitorBackendIcingadb; -use Icinga\Module\Director\Backend\MonitorBackendMonitoring; +use Icinga\Module\Director\Integration\MonitoringModule\Monitoring; use Icinga\Module\Director\Web\Controller\Extension\CoreApi; use Icinga\Module\Director\Web\Controller\Extension\DirectorDb; use Icinga\Module\Director\Web\Controller\Extension\RestApi; @@ -252,7 +252,7 @@ abstract class ActionController extends Controller implements ControlsAndContent if (Module::exists('icingadb')) { $this->backend = new MonitorBackendIcingadb(); } else { - $this->backend = new MonitorBackendMonitoring(); + $this->backend = new Monitoring($this->Auth()); } } From 604667ca65fff55b28b397e59fbca6a403dcbf7d Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Fri, 17 Nov 2023 12:56:07 +0100 Subject: [PATCH 05/22] Relocate Backend classes --- .../BackendInterface.php} | 4 ++-- .../Icingadb/IcingadbBackend.php} | 5 +++-- .../Integration/MonitoringModule/Monitoring.php | 4 ++-- .../Director/ProvidedHook/Icingadb/HostActions.php | 4 ++-- .../ProvidedHook/Icingadb/ServiceActions.php | 4 ++-- .../Director/Web/Controller/ActionController.php | 13 ++++++------- 6 files changed, 17 insertions(+), 17 deletions(-) rename library/Director/{Backend/MonitorBackend.php => Integration/BackendInterface.php} (84%) rename library/Director/{Backend/MonitorBackendIcingadb.php => Integration/Icingadb/IcingadbBackend.php} (91%) diff --git a/library/Director/Backend/MonitorBackend.php b/library/Director/Integration/BackendInterface.php similarity index 84% rename from library/Director/Backend/MonitorBackend.php rename to library/Director/Integration/BackendInterface.php index 5950d2c0..f8722c1b 100644 --- a/library/Director/Backend/MonitorBackend.php +++ b/library/Director/Integration/BackendInterface.php @@ -1,10 +1,10 @@ isAvailable() && $backend->canModifyHost($hostname)) { $allowEdit = IcingaHost::exists($hostname, $db); } diff --git a/library/Director/ProvidedHook/Icingadb/ServiceActions.php b/library/Director/ProvidedHook/Icingadb/ServiceActions.php index 383d915d..23f3fab9 100644 --- a/library/Director/ProvidedHook/Icingadb/ServiceActions.php +++ b/library/Director/ProvidedHook/Icingadb/ServiceActions.php @@ -4,8 +4,8 @@ namespace Icinga\Module\Director\ProvidedHook\Icingadb; use Exception; use Icinga\Application\Config; -use Icinga\Module\Director\Backend\MonitorBackendIcingadb; use Icinga\Module\Director\Db; +use Icinga\Module\Director\Integration\Icingadb\IcingadbBackend; use Icinga\Module\Director\Objects\IcingaHost; use Icinga\Module\Director\Util; use Icinga\Module\Icingadb\Hook\ServiceActionsHook; @@ -56,7 +56,7 @@ class ServiceActions extends ServiceActionsHook if (Util::hasPermission('director/hosts')) { $title = mt('director', 'Modify'); } elseif (Util::hasPermission('director/monitoring/services')) { - $backend = new MonitorBackendIcingadb(); + $backend = new IcingadbBackend(); if ($backend->isAvailable() && $backend->canModifyService($hostname, $serviceName) ) { diff --git a/library/Director/Web/Controller/ActionController.php b/library/Director/Web/Controller/ActionController.php index b1aadb96..72750b30 100644 --- a/library/Director/Web/Controller/ActionController.php +++ b/library/Director/Web/Controller/ActionController.php @@ -4,13 +4,12 @@ namespace Icinga\Module\Director\Web\Controller; use gipfl\Translation\StaticTranslator; use Icinga\Application\Benchmark; -use Icinga\Application\Icinga; use Icinga\Application\Modules\Module; use Icinga\Data\Paginatable; use Icinga\Exception\NotFoundError; use Icinga\Exception\ProgrammingError; -use Icinga\Module\Director\Backend\MonitorBackend; -use Icinga\Module\Director\Backend\MonitorBackendIcingadb; +use Icinga\Module\Director\Integration\Icingadb\IcingadbBackend; +use Icinga\Module\Director\Integration\BackendInterface; use Icinga\Module\Director\Integration\MonitoringModule\Monitoring; use Icinga\Module\Director\Web\Controller\Extension\CoreApi; use Icinga\Module\Director\Web\Controller\Extension\DirectorDb; @@ -40,7 +39,7 @@ abstract class ActionController extends Controller implements ControlsAndContent /** @var UrlParams Hint for IDE, somehow does not work in web */ protected $params; - /** @var MonitorBackend */ + /** @var BackendInterface */ private $backend; /** @@ -244,13 +243,13 @@ abstract class ActionController extends Controller implements ControlsAndContent } /** - * @return MonitorBackend + * @return BackendInterface */ - protected function backend() + protected function backend(): BackendInterface { if ($this->backend === null) { if (Module::exists('icingadb')) { - $this->backend = new MonitorBackendIcingadb(); + $this->backend = new IcingadbBackend(); } else { $this->backend = new Monitoring($this->Auth()); } From 8ea8a62ef46675b0ff1f3067ebc19968785b87d5 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Fri, 17 Nov 2023 13:30:02 +0100 Subject: [PATCH 06/22] BackendInterface: Add phpDocs --- .../Director/Integration/BackendInterface.php | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/library/Director/Integration/BackendInterface.php b/library/Director/Integration/BackendInterface.php index f8722c1b..4af6ae8d 100644 --- a/library/Director/Integration/BackendInterface.php +++ b/library/Director/Integration/BackendInterface.php @@ -6,15 +6,57 @@ use Icinga\Web\Url; interface BackendInterface { + /** + * Whether the backend is available + * + * @return bool + */ public function isAvailable(): bool; + /** + * Whether the backend has the given host + * + * @param string $hostname + * + * @return bool + */ public function hasHost(string $hostname): bool; + /** + * Whether the backend has the given service of the specified host + * + * @param string $hostname + * @param string $service + * + * @return bool + */ public function hasService(string $hostname, string $service): bool; + /** + * Whether an authenticated user has the permission (is not restricted) to modify given host + * + * @param string $hostName + * + * @return bool + */ public function canModifyHost(string $hostName): bool; + /** + * Whether an authenticated user has the permission (is not restricted) to modify given service of specified host + * + * @param string $hostName + * @param string $serviceName + * + * @return bool + */ public function canModifyService(string $hostName, string $serviceName): bool; + /** + * Get the url of given host + * + * @param string $hostname + * + * @return Url + */ public function getHostUrl(string $hostname): Url; } From 956cce84cb58b20d8484bae1d8d621069b45b512 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Fri, 17 Nov 2023 13:43:08 +0100 Subject: [PATCH 07/22] Cleanup code - Remove superfluous methods/usages - Simplify the code --- .../DirectorObject/Lookup/ServiceFinder.php | 2 +- .../Integration/Icingadb/IcingadbBackend.php | 27 ++++----------- .../MonitoringModule/Monitoring.php | 33 ++++--------------- .../Web/Controller/ActionController.php | 2 +- 4 files changed, 15 insertions(+), 49 deletions(-) diff --git a/library/Director/DirectorObject/Lookup/ServiceFinder.php b/library/Director/DirectorObject/Lookup/ServiceFinder.php index fba6b65e..45b586c8 100644 --- a/library/Director/DirectorObject/Lookup/ServiceFinder.php +++ b/library/Director/DirectorObject/Lookup/ServiceFinder.php @@ -68,7 +68,7 @@ class ServiceFinder } if ($this->auth->hasPermission(Permission::MONITORING_HOSTS)) { if ($info = $this::find($this->host, $serviceName)) { - if ((new Monitoring($this->auth))->canModifyService($this->host->getObjectName(), $serviceName)) { + if ((new Monitoring())->canModifyService($this->host->getObjectName(), $serviceName)) { return $info->getUrl(); } } diff --git a/library/Director/Integration/Icingadb/IcingadbBackend.php b/library/Director/Integration/Icingadb/IcingadbBackend.php index fcdfeacf..5279652c 100644 --- a/library/Director/Integration/Icingadb/IcingadbBackend.php +++ b/library/Director/Integration/Icingadb/IcingadbBackend.php @@ -2,16 +2,12 @@ namespace Icinga\Module\Director\Integration\Icingadb; -use gipfl\IcingaWeb2\Link; -use Icinga\Application\Icinga; -use Icinga\Data\Filter\Filter as DataFilter; +use Icinga\Application\Modules\Module; use Icinga\Module\Director\Integration\BackendInterface; -use Icinga\Module\Director\Objects\IcingaHost; use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Common\Database; use Icinga\Module\Icingadb\Model\Host; use Icinga\Module\Icingadb\Model\Service; -use Icinga\Module\Icingadb\Redis\VolatileStateResults; use Icinga\Web\Url; use ipl\Stdlib\Filter; @@ -22,28 +18,22 @@ class IcingadbBackend implements BackendInterface public function isAvailable(): bool { - $app = Icinga::app(); - $modules = $app->getModuleManager(); - return $modules->hasLoaded('icingadb'); + return Module::exists('icingadb'); } public function hasHost($hostname): bool { - $query = Host::on($this->getDb()); - $query->filter(Filter::equal('host.name', $hostname)); + $query = Host::on($this->getDb()) + ->filter(Filter::equal('host.name', $hostname)); $this->applyRestrictions($query); - /** @var Host $host */ - $host = $query->first(); - - return ($host !== null); + return $query->first() !== null; } public function hasService($hostname, $service): bool { - $query = Service::on($this->getDb()); - $query + $query = Service::on($this->getDb()) ->filter(Filter::all( Filter::equal('service.name', $service), Filter::equal('host.name', $hostname) @@ -51,10 +41,7 @@ class IcingadbBackend implements BackendInterface $this->applyRestrictions($query); - /** @var Service $service */ - $service = $query->first(); - - return ($service !== null); + return $query->first() !== null; } public function getHostUrl(string $hostname): Url diff --git a/library/Director/Integration/MonitoringModule/Monitoring.php b/library/Director/Integration/MonitoringModule/Monitoring.php index ccfa60ae..6d9fa201 100644 --- a/library/Director/Integration/MonitoringModule/Monitoring.php +++ b/library/Director/Integration/MonitoringModule/Monitoring.php @@ -39,11 +39,6 @@ class Monitoring implements BackendInterface } public function hasHost($hostname): bool - { - return $this->hasHostByName($hostname); - } - - public function hasHostByName($hostname): bool { if (! $this->isAvailable()) { return false; @@ -56,13 +51,7 @@ class Monitoring implements BackendInterface } } - public function hasService($hostname, $service): bool - { - return $this->hasServiceByName($hostname, $service); - } - - public function hasServiceByName($hostname, $service): bool { if (! $this->isAvailable()) { return false; @@ -77,23 +66,18 @@ class Monitoring implements BackendInterface public function canModifyService(string $hostName, string $serviceName): bool { - return $this->canModifyServiceByName($hostName, $serviceName); - } - - public function canModifyServiceByName($hostname, $service): bool - { - if (! $this->isAvailable() || $hostname === null || $service === null) { + if (! $this->isAvailable() || $hostName === null || $serviceName === null) { return false; } if ($this->auth->hasPermission(Permission::MONITORING_SERVICES)) { $restriction = null; foreach ($this->auth->getRestrictions(Restriction::MONITORING_RW_OBJECT_FILTER) as $restriction) { - if ($this->hasServiceWithFilter($hostname, $service, Filter::fromQueryString($restriction))) { + if ($this->hasServiceWithFilter($hostName, $serviceName, Filter::fromQueryString($restriction))) { return true; } } if ($restriction === null) { - return $this->hasServiceByName($hostname, $service); + return $this->hasService($hostName, $serviceName); } } @@ -101,21 +85,16 @@ class Monitoring implements BackendInterface } public function canModifyHost(string $hostName): bool - { - return $this->canModifyHostByName($hostName); - } - - public function canModifyHostByName($hostname): bool { if ($this->isAvailable() && $this->auth->hasPermission(Permission::MONITORING_HOSTS)) { $restriction = null; foreach ($this->auth->getRestrictions(Restriction::MONITORING_RW_OBJECT_FILTER) as $restriction) { - if ($this->hasHostWithFilter($hostname, Filter::fromQueryString($restriction))) { + if ($this->hasHostWithFilter($hostName, Filter::fromQueryString($restriction))) { return true; } } if ($restriction === null) { - return $this->hasHostByName($hostname); + return $this->hasHost($hostName); } } @@ -131,7 +110,7 @@ class Monitoring implements BackendInterface } } - public function hasServiceWithFilter($hostname, $service, Filter $filter): bool + protected function hasServiceWithFilter($hostname, $service, Filter $filter): bool { try { return $this->rowIsService( diff --git a/library/Director/Web/Controller/ActionController.php b/library/Director/Web/Controller/ActionController.php index 72750b30..bbff3a30 100644 --- a/library/Director/Web/Controller/ActionController.php +++ b/library/Director/Web/Controller/ActionController.php @@ -251,7 +251,7 @@ abstract class ActionController extends Controller implements ControlsAndContent if (Module::exists('icingadb')) { $this->backend = new IcingadbBackend(); } else { - $this->backend = new Monitoring($this->Auth()); + $this->backend = new Monitoring($this->getAuth()); } } From 677f5dc72a848bf898dd246d1b42993019492f57 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Fri, 17 Nov 2023 14:13:03 +0100 Subject: [PATCH 08/22] Monitoring/IcingadbBackend: Handle if $hostName or $serviceName is null --- .../Director/Integration/BackendInterface.php | 24 ++++++------- .../Integration/Icingadb/IcingadbBackend.php | 36 ++++++++++++++----- .../MonitoringModule/Monitoring.php | 26 ++++++++------ 3 files changed, 54 insertions(+), 32 deletions(-) diff --git a/library/Director/Integration/BackendInterface.php b/library/Director/Integration/BackendInterface.php index 4af6ae8d..e89e1392 100644 --- a/library/Director/Integration/BackendInterface.php +++ b/library/Director/Integration/BackendInterface.php @@ -16,47 +16,47 @@ interface BackendInterface /** * Whether the backend has the given host * - * @param string $hostname + * @param ?string $hostName * * @return bool */ - public function hasHost(string $hostname): bool; + public function hasHost(?string $hostName): bool; /** * Whether the backend has the given service of the specified host * - * @param string $hostname - * @param string $service + * @param ?string $hostName + * @param ?string $serviceName * * @return bool */ - public function hasService(string $hostname, string $service): bool; + public function hasService(?string $hostName, ?string $serviceName): bool; /** * Whether an authenticated user has the permission (is not restricted) to modify given host * - * @param string $hostName + * @param ?string $hostName * * @return bool */ - public function canModifyHost(string $hostName): bool; + public function canModifyHost(?string $hostName): bool; /** * Whether an authenticated user has the permission (is not restricted) to modify given service of specified host * - * @param string $hostName - * @param string $serviceName + * @param ?string $hostName + * @param ?string $serviceName * * @return bool */ - public function canModifyService(string $hostName, string $serviceName): bool; + public function canModifyService(?string $hostName, ?string $serviceName): bool; /** * Get the url of given host * - * @param string $hostname + * @param ?string $hostName * * @return Url */ - public function getHostUrl(string $hostname): Url; + public function getHostUrl(?string $hostName): ?Url; } diff --git a/library/Director/Integration/Icingadb/IcingadbBackend.php b/library/Director/Integration/Icingadb/IcingadbBackend.php index 5279652c..299b9ff9 100644 --- a/library/Director/Integration/Icingadb/IcingadbBackend.php +++ b/library/Director/Integration/Icingadb/IcingadbBackend.php @@ -21,22 +21,30 @@ class IcingadbBackend implements BackendInterface return Module::exists('icingadb'); } - public function hasHost($hostname): bool + public function hasHost(?string $hostName): bool { + if ($hostName === null) { + return false; + } + $query = Host::on($this->getDb()) - ->filter(Filter::equal('host.name', $hostname)); + ->filter(Filter::equal('host.name', $hostName)); $this->applyRestrictions($query); return $query->first() !== null; } - public function hasService($hostname, $service): bool + public function hasService(?string $hostName, ?string $serviceName): bool { + if ($hostName === null || $serviceName === null) { + return false; + } + $query = Service::on($this->getDb()) ->filter(Filter::all( - Filter::equal('service.name', $service), - Filter::equal('host.name', $hostname) + Filter::equal('service.name', $serviceName), + Filter::equal('host.name', $hostName) )); $this->applyRestrictions($query); @@ -44,19 +52,29 @@ class IcingadbBackend implements BackendInterface return $query->first() !== null; } - public function getHostUrl(string $hostname): Url + public function getHostUrl(?string $hostName): ?Url { - return Url::fromPath('icingadb/host', ['name' => $hostname]); + if ($hostName === null) { + return null; + } + + return Url::fromPath('icingadb/host', ['name' => $hostName]); } - public function canModifyHost(string $hostName): bool + public function canModifyHost(?string $hostName): bool { + if ($hostName === null) { + return false; + } // TODO: Implement canModifyService() method. return false; } - public function canModifyService(string $hostName, string $serviceName): bool + public function canModifyService(?string $hostName, ?string $serviceName): bool { + if ($hostName === null || $serviceName === null) { + return false; + } // TODO: Implement canModifyService() method. return false; } diff --git a/library/Director/Integration/MonitoringModule/Monitoring.php b/library/Director/Integration/MonitoringModule/Monitoring.php index 6d9fa201..82ea9968 100644 --- a/library/Director/Integration/MonitoringModule/Monitoring.php +++ b/library/Director/Integration/MonitoringModule/Monitoring.php @@ -33,38 +33,42 @@ class Monitoring implements BackendInterface return $this->backend !== null; } - public function getHostUrl(string $hostname): Url + public function getHostUrl(?string $hostName): ?Url { - return Url::fromPath('monitoring/host/show', ['host' => $hostname]); + if ($hostName === null) { + return null; + } + + return Url::fromPath('monitoring/host/show', ['host' => $hostName]); } - public function hasHost($hostname): bool + public function hasHost(?string $hostName): bool { - if (! $this->isAvailable()) { + if ($hostName === null || ! $this->isAvailable()) { return false; } try { - return $this->selectHost($hostname)->fetchOne() === $hostname; + return $this->selectHost($hostName)->fetchOne() === $hostName; } catch (Exception $_) { return false; } } - public function hasService($hostname, $service): bool + public function hasService(?string $hostName, ?string $serviceName): bool { - if (! $this->isAvailable()) { + if ($hostName === null || $serviceName === null || ! $this->isAvailable()) { return false; } try { - return $this->rowIsService($this->selectService($hostname, $service)->fetchRow(), $hostname, $service); + return $this->rowIsService($this->selectService($hostName, $serviceName)->fetchRow(), $hostName, $serviceName); } catch (Exception $_) { return false; } } - public function canModifyService(string $hostName, string $serviceName): bool + public function canModifyService(?string $hostName, ?string $serviceName): bool { if (! $this->isAvailable() || $hostName === null || $serviceName === null) { return false; @@ -84,9 +88,9 @@ class Monitoring implements BackendInterface return false; } - public function canModifyHost(string $hostName): bool + public function canModifyHost(?string $hostName): bool { - if ($this->isAvailable() && $this->auth->hasPermission(Permission::MONITORING_HOSTS)) { + if ($hostName !== null && $this->isAvailable() && $this->auth->hasPermission(Permission::MONITORING_HOSTS)) { $restriction = null; foreach ($this->auth->getRestrictions(Restriction::MONITORING_RW_OBJECT_FILTER) as $restriction) { if ($this->hasHostWithFilter($hostName, Filter::fromQueryString($restriction))) { From eeaf87741a479d07a7bd2ae9da1f2caa57ad6a58 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Fri, 17 Nov 2023 15:30:52 +0100 Subject: [PATCH 09/22] IcingadbBackend: Always check if module is available --- .../Integration/Icingadb/IcingadbBackend.php | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/library/Director/Integration/Icingadb/IcingadbBackend.php b/library/Director/Integration/Icingadb/IcingadbBackend.php index 299b9ff9..c0f749c6 100644 --- a/library/Director/Integration/Icingadb/IcingadbBackend.php +++ b/library/Director/Integration/Icingadb/IcingadbBackend.php @@ -16,14 +16,22 @@ class IcingadbBackend implements BackendInterface use Database; use Auth; + /** @var bool */ + protected $isAvailable; + + public function __construct() + { + $this->isAvailable = Module::exists('icingadb'); + } + public function isAvailable(): bool { - return Module::exists('icingadb'); + return $this->isAvailable; } public function hasHost(?string $hostName): bool { - if ($hostName === null) { + if ($hostName === null || ! $this->isAvailable()) { return false; } @@ -37,7 +45,7 @@ class IcingadbBackend implements BackendInterface public function hasService(?string $hostName, ?string $serviceName): bool { - if ($hostName === null || $serviceName === null) { + if ($hostName === null || $serviceName === null || ! $this->isAvailable()) { return false; } @@ -54,7 +62,7 @@ class IcingadbBackend implements BackendInterface public function getHostUrl(?string $hostName): ?Url { - if ($hostName === null) { + if ($hostName === null || ! $this->isAvailable()) { return null; } @@ -63,7 +71,7 @@ class IcingadbBackend implements BackendInterface public function canModifyHost(?string $hostName): bool { - if ($hostName === null) { + if ($hostName === null || ! $this->isAvailable()) { return false; } // TODO: Implement canModifyService() method. @@ -72,7 +80,7 @@ class IcingadbBackend implements BackendInterface public function canModifyService(?string $hostName, ?string $serviceName): bool { - if ($hostName === null || $serviceName === null) { + if ($hostName === null || $serviceName === null || ! $this->isAvailable()) { return false; } // TODO: Implement canModifyService() method. From db7181c29e9715202b3b20d78ea676a86dda91f0 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Fri, 17 Nov 2023 16:16:27 +0100 Subject: [PATCH 10/22] Backend: Remove unnecessary calls to isAvailable() --- application/controllers/HostController.php | 1 - library/Director/ProvidedHook/Icingadb/HostActions.php | 3 +-- library/Director/ProvidedHook/Icingadb/ServiceActions.php | 5 +---- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/application/controllers/HostController.php b/application/controllers/HostController.php index cce491e2..da873a61 100644 --- a/application/controllers/HostController.php +++ b/application/controllers/HostController.php @@ -568,7 +568,6 @@ class HostController extends ObjectController try { $backend = $this->backend(); if ($host instanceof IcingaHost - && $backend->isAvailable() && $host->isObject() && $backend->hasHost($host->getObjectName()) ) { diff --git a/library/Director/ProvidedHook/Icingadb/HostActions.php b/library/Director/ProvidedHook/Icingadb/HostActions.php index 4fa636c0..f69f24c6 100644 --- a/library/Director/ProvidedHook/Icingadb/HostActions.php +++ b/library/Director/ProvidedHook/Icingadb/HostActions.php @@ -44,8 +44,7 @@ class HostActions extends HostActionsHook $allowEdit = true; } if (Util::hasPermission('director/monitoring/hosts')) { - $backend = new IcingadbBackend(); - if ($backend->isAvailable() && $backend->canModifyHost($hostname)) { + if ((new IcingadbBackend())->canModifyHost($hostname)) { $allowEdit = IcingaHost::exists($hostname, $db); } } diff --git a/library/Director/ProvidedHook/Icingadb/ServiceActions.php b/library/Director/ProvidedHook/Icingadb/ServiceActions.php index 23f3fab9..337754e9 100644 --- a/library/Director/ProvidedHook/Icingadb/ServiceActions.php +++ b/library/Director/ProvidedHook/Icingadb/ServiceActions.php @@ -56,10 +56,7 @@ class ServiceActions extends ServiceActionsHook if (Util::hasPermission('director/hosts')) { $title = mt('director', 'Modify'); } elseif (Util::hasPermission('director/monitoring/services')) { - $backend = new IcingadbBackend(); - if ($backend->isAvailable() - && $backend->canModifyService($hostname, $serviceName) - ) { + if ((new IcingadbBackend())->canModifyService($hostname, $serviceName)) { $title = mt('director', 'Modify'); } } elseif (Util::hasPermission('director/monitoring/services-ro')) { From a272b0d2423fd755fa859d1696018eb7eac5be9a Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Fri, 17 Nov 2023 16:49:26 +0100 Subject: [PATCH 11/22] Introduce icingadb permissions/restrictions --- library/Director/Auth/Permission.php | 3 +++ library/Director/Auth/Restriction.php | 1 + 2 files changed, 4 insertions(+) diff --git a/library/Director/Auth/Permission.php b/library/Director/Auth/Permission.php index 86ced76a..c29d7898 100644 --- a/library/Director/Auth/Permission.php +++ b/library/Director/Auth/Permission.php @@ -17,6 +17,9 @@ class Permission public const MONITORING_SERVICES_RO = 'director/monitoring/services-ro'; public const MONITORING_SERVICES = 'director/monitoring/services'; public const MONITORING_HOSTS = 'director/monitoring/hosts'; + public const ICINGADB_SERVICES_RO = 'director/icingadb/services-ro'; + public const ICINGADB_SERVICES = 'director/icingadb/services'; + public const ICINGADB_HOSTS = 'director/icingadb/hosts'; public const NOTIFICATIONS = 'director/notifications'; public const SCHEDULED_DOWNTIMES = 'director/scheduled-downtimes'; public const SERVICES = 'director/services'; diff --git a/library/Director/Auth/Restriction.php b/library/Director/Auth/Restriction.php index d56f71ff..3394dccd 100644 --- a/library/Director/Auth/Restriction.php +++ b/library/Director/Auth/Restriction.php @@ -5,6 +5,7 @@ namespace Icinga\Module\Director\Auth; class Restriction { public const MONITORING_RW_OBJECT_FILTER = 'director/monitoring/rw-object-filter'; + public const ICINGADB_RW_OBJECT_FILTER = 'director/icingadb/rw-object-filter'; public const FILTER_HOSTGROUPS = 'director/filter/hostgroups'; // Hint: by-name-Filters are being fetched with variable names, like "director/$type/apply/filter-by-name" From 1048c33fa4a59f88788e31fda86486a818e4634a Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Fri, 17 Nov 2023 16:51:56 +0100 Subject: [PATCH 12/22] configuration.php: Only provide monitoring/icingadb permissions/restrictions if module exists --- configuration.php | 54 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/configuration.php b/configuration.php index eb05d4fc..f812f3c4 100644 --- a/configuration.php +++ b/configuration.php @@ -1,15 +1,19 @@ getConfig()->get('frontend', 'disabled', 'no') === 'yes') { return; } +$monitoringExists = Module::exists('monitoring'); +$icingadbExists = Module::exists('icingadb'); + $this->providePermission(Permission::ALL_PERMISSIONS, $this->translate('Allow unrestricted access to Icinga Director')); $this->providePermission(Permission::API, $this->translate('Allow to access the director API')); $this->providePermission(Permission::AUDIT, $this->translate('Allow to access the full audit log')); @@ -37,22 +41,46 @@ $this->providePermission(Permission::USERS, $this->translate('Allow to configure $this->providePermission(Permission::SCHEDULED_DOWNTIMES, $this->translate( 'Allow to configure notifications (unrestricted)' )); -$this->providePermission(Permission::MONITORING_HOSTS, $this->translate( - 'Allow users to modify Hosts they are allowed to see in the monitoring module' -)); -$this->providePermission(Permission::MONITORING_SERVICES, $this->translate( - 'Allow users to modify Service they are allowed to see in the monitoring module' -)); -$this->providePermission(Permission::MONITORING_SERVICES_RO, $this->translate( - 'Allow readonly users to see where a Service came from' -)); + +if ($monitoringExists) { + $this->providePermission(Permission::MONITORING_HOSTS, $this->translate( + 'Allow users to modify Hosts they are allowed to see in the monitoring module' + )); + $this->providePermission(Permission::MONITORING_SERVICES, $this->translate( + 'Allow users to modify Service they are allowed to see in the monitoring module' + )); + $this->providePermission(Permission::MONITORING_SERVICES_RO, $this->translate( + 'Allow readonly users to see where a Service came from' + )); +} + +if ($icingadbExists) { + $this->providePermission(Permission::ICINGADB_HOSTS, $this->translate( + 'Allow users to modify Hosts they are allowed to see in Icinga DB Web' + )); + $this->providePermission(Permission::ICINGADB_SERVICES, $this->translate( + 'Allow users to modify Service they are allowed to see in Icinga DB Web' + )); + $this->providePermission(Permission::ICINGADB_SERVICES_RO, $this->translate( + 'Allow readonly users to see where a Service came from' + )); +} + +if ($monitoringExists) { + $this->provideRestriction(Restriction::MONITORING_RW_OBJECT_FILTER, $this->translate( + 'Additional (monitoring module) object filter to further restrict write access' + )); +} + +if ($icingadbExists) { + $this->provideRestriction(Restriction::ICINGADB_RW_OBJECT_FILTER, $this->translate( + 'Additional (Icinga DB Web) object filter to further restrict write access' + )); +} $this->provideRestriction(Restriction::FILTER_HOSTGROUPS, $this->translate( 'Limit access to the given comma-separated list of hostgroups' )); -$this->provideRestriction(Restriction::MONITORING_RW_OBJECT_FILTER, $this->translate( - 'Additional (monitoring module) object filter to further restrict write access' -)); $this->provideRestriction(Restriction::NOTIFICATION_APPLY_FILTER_BY_NAME, $this->translate( 'Filter available notification apply rules' )); From 26f8769d28451caefac4aad2ac109401d802aeda Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Mon, 20 Nov 2023 15:20:15 +0100 Subject: [PATCH 13/22] Icingadb (Host/Service)Actions: Fix permissions and code style --- .../ProvidedHook/Icingadb/HostActions.php | 20 ++++++++------ .../ProvidedHook/Icingadb/ServiceActions.php | 27 +++++++++---------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/library/Director/ProvidedHook/Icingadb/HostActions.php b/library/Director/ProvidedHook/Icingadb/HostActions.php index f69f24c6..d7332eae 100644 --- a/library/Director/ProvidedHook/Icingadb/HostActions.php +++ b/library/Director/ProvidedHook/Icingadb/HostActions.php @@ -4,6 +4,7 @@ namespace Icinga\Module\Director\ProvidedHook\Icingadb; use Exception; use Icinga\Application\Config; +use Icinga\Module\Director\Auth\Permission; use Icinga\Module\Director\Db; use Icinga\Module\Director\Integration\Icingadb\IcingadbBackend; use Icinga\Module\Director\Objects\IcingaHost; @@ -20,30 +21,33 @@ class HostActions extends HostActionsHook try { return $this->getThem($host); } catch (Exception $e) { - return array(); + return []; } } protected function getThem(Host $host): array { - $actions = array(); + $actions = []; $db = $this->db(); if (! $db) { return $actions; } $hostname = $host->name; - if (Util::hasPermission('director/inspect')) { - $actions[mt('director', 'Inspect')] = Url::fromPath( - 'director/inspect/object', - array('type' => 'host', 'plural' => 'hosts', 'name' => $hostname) + if (Util::hasPermission(Permission::INSPECT)) { + $actions[] = new Link( + mt('director', 'Inspect'), + Url::fromPath( + 'director/inspect/object', + ['type' => 'host', 'plural' => 'hosts', 'name' => $hostname] + ) ); } $allowEdit = false; - if (Util::hasPermission('director/hosts') && IcingaHost::exists($hostname, $db)) { + if (Util::hasPermission(Permission::HOSTS) && IcingaHost::exists($hostname, $db)) { $allowEdit = true; } - if (Util::hasPermission('director/monitoring/hosts')) { + if (Util::hasPermission(Permission::ICINGADB_HOSTS)) { if ((new IcingadbBackend())->canModifyHost($hostname)) { $allowEdit = IcingaHost::exists($hostname, $db); } diff --git a/library/Director/ProvidedHook/Icingadb/ServiceActions.php b/library/Director/ProvidedHook/Icingadb/ServiceActions.php index 337754e9..1603dc37 100644 --- a/library/Director/ProvidedHook/Icingadb/ServiceActions.php +++ b/library/Director/ProvidedHook/Icingadb/ServiceActions.php @@ -4,6 +4,7 @@ namespace Icinga\Module\Director\ProvidedHook\Icingadb; use Exception; use Icinga\Application\Config; +use Icinga\Module\Director\Auth\Permission; use Icinga\Module\Director\Db; use Icinga\Module\Director\Integration\Icingadb\IcingadbBackend; use Icinga\Module\Director\Objects\IcingaHost; @@ -20,7 +21,6 @@ class ServiceActions extends ServiceActionsHook try { return $this->getThem($service); } catch (Exception $e) { - die($e); return []; } } @@ -40,26 +40,25 @@ class ServiceActions extends ServiceActionsHook $hostname = $service->host->name; $serviceName = $service->name; - if (Util::hasPermission('director/inspect')) { - $actions[mt('director', 'Inspect')] = Url::fromPath('director/inspect/object', [ - 'type' => 'service', - 'plural' => 'services', - 'name' => sprintf( - '%s!%s', - $hostname, - $serviceName - ) - ]); + if (Util::hasPermission(Permission::INSPECT)) { + $actions[] = new Link( + mt('director', 'Inspect'), + Url::fromPath('director/inspect/object', [ + 'type' => 'service', + 'plural' => 'services', + 'name' => sprintf('%s!%s', $hostname, $serviceName) + ]) + ); } $title = null; - if (Util::hasPermission('director/hosts')) { + if (Util::hasPermission(Permission::HOSTS)) { $title = mt('director', 'Modify'); - } elseif (Util::hasPermission('director/monitoring/services')) { + } elseif (Util::hasPermission(Permission::ICINGADB_SERVICES)) { if ((new IcingadbBackend())->canModifyService($hostname, $serviceName)) { $title = mt('director', 'Modify'); } - } elseif (Util::hasPermission('director/monitoring/services-ro')) { + } elseif (Util::hasPermission(Permission::ICINGADB_SERVICES_RO)) { $title = mt('director', 'Configuration'); } From 4e6528e8626d183f125bf6318ce4e7024192ebe3 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Mon, 20 Nov 2023 15:57:14 +0100 Subject: [PATCH 14/22] ServiceController: Remove redudant if condition --- application/controllers/ServiceController.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/application/controllers/ServiceController.php b/application/controllers/ServiceController.php index c09b0937..90f6ae50 100644 --- a/application/controllers/ServiceController.php +++ b/application/controllers/ServiceController.php @@ -29,12 +29,11 @@ class ServiceController extends ObjectController protected function checkDirectorPermissions() { - if ($this->hasPermission(Permission::MONITORING_SERVICES)) { - if ($this->backend()->canModifyService($this->getParam('host'), $this->getParam('name'))) { - return; - } + if ($this->backend()->canModifyService($this->getParam('host'), $this->getParam('name'))) { + return; } - $this->assertPermission('director/hosts'); + + $this->assertPermission(Permission::HOSTS); } public function init() From 8a489bcc46017743ae957256c14bef7e4660b15c Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Tue, 21 Nov 2023 09:27:40 +0100 Subject: [PATCH 15/22] HostController: Move ServiceFinder::getRedirectionUrl() method code to findserviceAction() - This helps to detect backend easily, and was only called in this method anyway. - Add and use helping method getServicesReadOnlyPermission() - --- application/controllers/HostController.php | 50 ++++++++++++++++--- .../DirectorObject/Lookup/ServiceFinder.php | 34 ------------- 2 files changed, 44 insertions(+), 40 deletions(-) diff --git a/application/controllers/HostController.php b/application/controllers/HostController.php index da873a61..d5acdfc7 100644 --- a/application/controllers/HostController.php +++ b/application/controllers/HostController.php @@ -4,6 +4,8 @@ namespace Icinga\Module\Director\Controllers; use gipfl\Web\Widget\Hint; use Icinga\Module\Director\Auth\Permission; +use Icinga\Module\Director\Integration\Icingadb\IcingadbBackend; +use Icinga\Module\Director\Integration\MonitoringModule\Monitoring; use Icinga\Module\Director\Web\Table\ObjectsTableService; use ipl\Html\Html; use gipfl\IcingaWeb2\Link; @@ -39,7 +41,7 @@ class HostController extends ObjectController ) { return; } - if ($auth->hasPermission(Permission::MONITORING_SERVICES_RO) && $this->isServicesReadOnlyAction()) { + if ($this->isServicesReadOnlyAction() && $auth->hasPermission($this->getServicesReadOnlyPermission())) { return; } if ($auth->hasPermission(Permission::HOSTS)) { // faster @@ -136,11 +138,35 @@ class HostController extends ObjectController public function findserviceAction() { + $auth = $this->Auth(); $host = $this->getHostObject(); - $this->redirectNow( - (new ServiceFinder($host, $this->getAuth())) - ->getRedirectionUrl($this->params->get('service')) - ); + $hostName = $host->getObjectName(); + $serviceName = $this->params->get('service'); + $info = ServiceFinder::find($host, $serviceName); + $backend = $this->backend(); + + if ($info && $auth->hasPermission(Permission::HOSTS)) { + $redirectUrl = $info->getUrl(); + } elseif ($info + && (($backend instanceof Monitoring && $auth->hasPermission(Permission::MONITORING_HOSTS)) + || ($backend instanceof IcingadbBackend && $auth->hasPermission(Permission::ICINGADB_HOSTS)) + ) + && $backend->canModifyService($hostName, $serviceName) + ) { + $redirectUrl = $info->getUrl(); + } elseif ($auth->hasPermission($this->getServicesReadOnlyPermission())) { + $redirectUrl = Url::fromPath('director/host/servicesro', [ + 'name' => $hostName, + 'service' => $serviceName + ]); + } else { + $redirectUrl = Url::fromPath('director/host/invalidservice', [ + 'name' => $hostName, + 'service' => $serviceName, + ]); + } + + $this->redirectNow($redirectUrl); } /** @@ -263,7 +289,7 @@ class HostController extends ObjectController */ public function servicesroAction() { - $this->assertPermission(Permission::MONITORING_SERVICES_RO); + $this->assertPermission($this->getServicesReadOnlyPermission()); $host = $this->getHostObject(); $service = $this->params->getRequired('service'); $db = $this->db(); @@ -618,4 +644,16 @@ class HostController extends ObjectController } return $this->object; } + + /** + * Get readOnly permission of the service for the current backend + * + * @return string permission + */ + protected function getServicesReadOnlyPermission(): string + { + return $this->backend() instanceof IcingadbBackend + ? Permission::ICINGADB_SERVICES_RO + : Permission::MONITORING_SERVICES_RO; + } } diff --git a/library/Director/DirectorObject/Lookup/ServiceFinder.php b/library/Director/DirectorObject/Lookup/ServiceFinder.php index 45b586c8..a14d8538 100644 --- a/library/Director/DirectorObject/Lookup/ServiceFinder.php +++ b/library/Director/DirectorObject/Lookup/ServiceFinder.php @@ -51,38 +51,4 @@ class ServiceFinder return false; } - - /** - * @param $serviceName - * @return Url - */ - public function getRedirectionUrl($serviceName) - { - if ($this->auth === null) { - throw new RuntimeException('Auth is required for ServiceFinder when dealing when asking for URLs'); - } - if ($this->auth->hasPermission(Permission::HOSTS)) { - if ($info = $this::find($this->host, $serviceName)) { - return $info->getUrl(); - } - } - if ($this->auth->hasPermission(Permission::MONITORING_HOSTS)) { - if ($info = $this::find($this->host, $serviceName)) { - if ((new Monitoring())->canModifyService($this->host->getObjectName(), $serviceName)) { - return $info->getUrl(); - } - } - } - if ($this->auth->hasPermission(Permission::MONITORING_SERVICES_RO)) { - return Url::fromPath('director/host/servicesro', [ - 'name' => $this->host->getObjectName(), - 'service' => $serviceName - ]); - } - - return Url::fromPath('director/host/invalidservice', [ - 'name' => $this->host->getObjectName(), - 'service' => $serviceName, - ]); - } } From f52d05de31922b9a824075dc6277b32e5b32c6f1 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Tue, 21 Nov 2023 12:35:10 +0100 Subject: [PATCH 16/22] IcingadbBackend: Apply director restrictions properly --- .../Integration/Icingadb/IcingadbBackend.php | 105 ++++++++++++++---- 1 file changed, 84 insertions(+), 21 deletions(-) diff --git a/library/Director/Integration/Icingadb/IcingadbBackend.php b/library/Director/Integration/Icingadb/IcingadbBackend.php index c0f749c6..f76751cf 100644 --- a/library/Director/Integration/Icingadb/IcingadbBackend.php +++ b/library/Director/Integration/Icingadb/IcingadbBackend.php @@ -3,12 +3,15 @@ namespace Icinga\Module\Director\Integration\Icingadb; use Icinga\Application\Modules\Module; +use Icinga\Module\Director\Auth\Permission; +use Icinga\Module\Director\Auth\Restriction; use Icinga\Module\Director\Integration\BackendInterface; use Icinga\Module\Icingadb\Common\Auth; use Icinga\Module\Icingadb\Common\Database; use Icinga\Module\Icingadb\Model\Host; use Icinga\Module\Icingadb\Model\Service; use Icinga\Web\Url; +use ipl\Orm\Query; use ipl\Stdlib\Filter; class IcingadbBackend implements BackendInterface @@ -35,12 +38,7 @@ class IcingadbBackend implements BackendInterface return false; } - $query = Host::on($this->getDb()) - ->filter(Filter::equal('host.name', $hostName)); - - $this->applyRestrictions($query); - - return $query->first() !== null; + return $this->getHostQuery($hostName)->first() !== null; } public function hasService(?string $hostName, ?string $serviceName): bool @@ -49,15 +47,7 @@ class IcingadbBackend implements BackendInterface return false; } - $query = Service::on($this->getDb()) - ->filter(Filter::all( - Filter::equal('service.name', $serviceName), - Filter::equal('host.name', $hostName) - )); - - $this->applyRestrictions($query); - - return $query->first() !== null; + return $this->getServiceQuery($hostName, $serviceName)->first() !== null; } public function getHostUrl(?string $hostName): ?Url @@ -71,19 +61,92 @@ class IcingadbBackend implements BackendInterface public function canModifyHost(?string $hostName): bool { - if ($hostName === null || ! $this->isAvailable()) { + if ($hostName === null + || ! $this->isAvailable() + || ! $this->getAuth()->hasPermission(Permission::ICINGADB_HOSTS) + ) { return false; } - // TODO: Implement canModifyService() method. - return false; + + $query = $this->getHostQuery($hostName); + $this->applyDirectorRestrictions($query); + + return $query->first() !== null; } public function canModifyService(?string $hostName, ?string $serviceName): bool { - if ($hostName === null || $serviceName === null || ! $this->isAvailable()) { + if ($hostName === null + || $serviceName === null + || ! $this->isAvailable() + || ! $this->getAuth()->hasPermission(Permission::ICINGADB_SERVICES) + ) { return false; } - // TODO: Implement canModifyService() method. - return false; + + $query = $this->getServiceQuery($hostName, $serviceName); + $this->applyDirectorRestrictions($query); + + return $query->first() !== null; + } + + /** + * Get the query for given host + * + * @param string $hostName + * + * @return Query + */ + protected function getHostQuery(string $hostName): Query + { + $query = Host::on($this->getDb()) + ->filter(Filter::equal('host.name', $hostName)); + + $this->applyRestrictions($query); + + return $query; + } + + /** + * Get the query for given host and service + * + * @param string $hostName + * @param string $serviceName + * + * @return Query + */ + protected function getServiceQuery(string $hostName, string $serviceName): Query + { + $query = Service::on($this->getDb()) + ->filter(Filter::all( + Filter::equal('service.name', $serviceName), + Filter::equal('host.name', $hostName) + )); + + $this->applyRestrictions($query); + + return $query; + } + + /** + * Apply director restrictions on the given query + * + * @param Query $query + */ + protected function applyDirectorRestrictions(Query $query): void + { + $queryFilter = Filter::any(); + foreach ($this->getAuth()->getUser()->getRoles() as $role) { + $roleFilter = Filter::all(); + if ($restriction = $role->getRestrictions(Restriction::ICINGADB_RW_OBJECT_FILTER)) { + $roleFilter->add($this->parseRestriction($restriction, Restriction::ICINGADB_RW_OBJECT_FILTER)); + } + + if (! $roleFilter->isEmpty()) { + $queryFilter->add($roleFilter); + } + } + + $query->filter($queryFilter); } } From 4ef7f5664a7896642a0f48dc46815e5e34d793a3 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Tue, 21 Nov 2023 13:07:16 +0100 Subject: [PATCH 17/22] ActionController::backend(): Add condition to check which backend should be used - If both are available --- library/Director/Web/Controller/ActionController.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/Director/Web/Controller/ActionController.php b/library/Director/Web/Controller/ActionController.php index bbff3a30..2e01bdaa 100644 --- a/library/Director/Web/Controller/ActionController.php +++ b/library/Director/Web/Controller/ActionController.php @@ -11,6 +11,7 @@ use Icinga\Exception\ProgrammingError; use Icinga\Module\Director\Integration\Icingadb\IcingadbBackend; use Icinga\Module\Director\Integration\BackendInterface; use Icinga\Module\Director\Integration\MonitoringModule\Monitoring; +use Icinga\Module\Director\ProvidedHook\Icingadb\IcingadbSupport; use Icinga\Module\Director\Web\Controller\Extension\CoreApi; use Icinga\Module\Director\Web\Controller\Extension\DirectorDb; use Icinga\Module\Director\Web\Controller\Extension\RestApi; @@ -248,7 +249,7 @@ abstract class ActionController extends Controller implements ControlsAndContent protected function backend(): BackendInterface { if ($this->backend === null) { - if (Module::exists('icingadb')) { + if (Module::exists('icingadb') && IcingadbSupport::useIcingaDbAsBackend()) { $this->backend = new IcingadbBackend(); } else { $this->backend = new Monitoring($this->getAuth()); From d26a6195772a66b95170839add8f6c8fcbee1f66 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Thu, 30 Nov 2023 15:28:29 +0100 Subject: [PATCH 18/22] ServiceController: Use given properties to get host/service name --- application/controllers/ServiceController.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/application/controllers/ServiceController.php b/application/controllers/ServiceController.php index 90f6ae50..b62f317e 100644 --- a/application/controllers/ServiceController.php +++ b/application/controllers/ServiceController.php @@ -29,7 +29,10 @@ class ServiceController extends ObjectController protected function checkDirectorPermissions() { - if ($this->backend()->canModifyService($this->getParam('host'), $this->getParam('name'))) { + if ($this->host + && $this->object + && $this->backend()->canModifyService($this->host->getObjectName(), $this->object->getObjectName()) + ) { return; } From d30a56a385b4a97c8946864932ec58f3deb82833 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Tue, 21 Nov 2023 14:22:28 +0100 Subject: [PATCH 19/22] Fix phpcs issues --- application/controllers/HostController.php | 15 ++++++++------- .../Integration/MonitoringModule/Monitoring.php | 6 +++++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/application/controllers/HostController.php b/application/controllers/HostController.php index d5acdfc7..33b5ba5e 100644 --- a/application/controllers/HostController.php +++ b/application/controllers/HostController.php @@ -597,13 +597,14 @@ class HostController extends ObjectController && $host->isObject() && $backend->hasHost($host->getObjectName()) ) { - $this->actions()->add(Link::create($this->translate('Show'), - $backend->getHostUrl($host->getObjectName()), - null, - [ - 'class' => 'icon-globe critical', - 'data-base-target' => '_next' - ])); + $this->actions()->add( + Link::create( + $this->translate('Show'), + $backend->getHostUrl($host->getObjectName()), + null, + ['class' => 'icon-globe critical', 'data-base-target' => '_next'] + ) + ); // Intentionally placed here, show it only for deployed Hosts $this->addOptionalInspectLink(); diff --git a/library/Director/Integration/MonitoringModule/Monitoring.php b/library/Director/Integration/MonitoringModule/Monitoring.php index 82ea9968..cb574feb 100644 --- a/library/Director/Integration/MonitoringModule/Monitoring.php +++ b/library/Director/Integration/MonitoringModule/Monitoring.php @@ -62,7 +62,11 @@ class Monitoring implements BackendInterface } try { - return $this->rowIsService($this->selectService($hostName, $serviceName)->fetchRow(), $hostName, $serviceName); + return $this->rowIsService( + $this->selectService($hostName, $serviceName)->fetchRow(), + $hostName, + $serviceName + ); } catch (Exception $_) { return false; } From 147170e58a7acda466189ab829b547dc504e8cb1 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Mon, 4 Dec 2023 10:15:49 +0100 Subject: [PATCH 20/22] phpstan: Add icingadb module --- .github/workflows/php.yml | 1 + phpstan.neon | 2 ++ 2 files changed, 3 insertions(+) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index d163be2b..49e47982 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -37,6 +37,7 @@ jobs: sudo git clone --depth 1 -b snapshot/nightly https://github.com/Icinga/icinga-php-thirdparty.git /usr/share/icinga-php/vendor sudo git clone --depth 1 -b snapshot/nightly https://github.com/Icinga/icinga-php-library.git /usr/share/icinga-php/ipl sudo git clone --depth 1 https://github.com/Icinga/icingaweb2-module-cube.git /usr/share/icingaweb2-modules/cube + sudo git clone --depth 1 https://github.com/Icinga/icingadb-web.git /usr/share/icingaweb2-modules/icingadb - name: Setup Incubator run: | diff --git a/phpstan.neon b/phpstan.neon index 1db016e6..4e67c770 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -21,6 +21,7 @@ parameters: - /usr/share/icinga-php - /usr/share/icingaweb2-modules/incubator - /usr/share/icingaweb2-modules/cube + - /usr/share/icingaweb2-modules/icingadb excludePaths: - library/Director/CoreBeta @@ -33,3 +34,4 @@ parameters: - Icinga\Module\Monitoring\DataView\DataView - Icinga\Web\Session\SessionNamespace - Icinga\User\Preferences + - ipl\Orm\Model From 2461724271a74d544f89d9555ddb746c79f3f1b8 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Mon, 15 Jan 2024 16:06:11 +0100 Subject: [PATCH 21/22] IcingadbBackend: Drop icingadb restriction check and only check for director restrictions Monitoring does the same. --- .../Integration/Icingadb/IcingadbBackend.php | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/library/Director/Integration/Icingadb/IcingadbBackend.php b/library/Director/Integration/Icingadb/IcingadbBackend.php index f76751cf..532c537f 100644 --- a/library/Director/Integration/Icingadb/IcingadbBackend.php +++ b/library/Director/Integration/Icingadb/IcingadbBackend.php @@ -69,7 +69,6 @@ class IcingadbBackend implements BackendInterface } $query = $this->getHostQuery($hostName); - $this->applyDirectorRestrictions($query); return $query->first() !== null; } @@ -85,7 +84,6 @@ class IcingadbBackend implements BackendInterface } $query = $this->getServiceQuery($hostName, $serviceName); - $this->applyDirectorRestrictions($query); return $query->first() !== null; } @@ -102,7 +100,7 @@ class IcingadbBackend implements BackendInterface $query = Host::on($this->getDb()) ->filter(Filter::equal('host.name', $hostName)); - $this->applyRestrictions($query); + $this->applyDirectorRestrictions($query); return $query; } @@ -123,7 +121,7 @@ class IcingadbBackend implements BackendInterface Filter::equal('host.name', $hostName) )); - $this->applyRestrictions($query); + $this->applyDirectorRestrictions($query); return $query; } @@ -136,15 +134,8 @@ class IcingadbBackend implements BackendInterface protected function applyDirectorRestrictions(Query $query): void { $queryFilter = Filter::any(); - foreach ($this->getAuth()->getUser()->getRoles() as $role) { - $roleFilter = Filter::all(); - if ($restriction = $role->getRestrictions(Restriction::ICINGADB_RW_OBJECT_FILTER)) { - $roleFilter->add($this->parseRestriction($restriction, Restriction::ICINGADB_RW_OBJECT_FILTER)); - } - - if (! $roleFilter->isEmpty()) { - $queryFilter->add($roleFilter); - } + foreach ($this->getAuth()->getRestrictions(Restriction::ICINGADB_RW_OBJECT_FILTER) as $restriction) { + $queryFilter->add($this->parseRestriction($restriction, Restriction::ICINGADB_RW_OBJECT_FILTER)); } $query->filter($queryFilter); From a850ff13d76c3932da3882e68146b20e1d1c5bf1 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Tue, 16 Jan 2024 10:27:10 +0100 Subject: [PATCH 22/22] IcingadbBackend: Remove isAvailable method and property As it is only used internally now, it is no more required --- .../Director/Integration/BackendInterface.php | 7 ------ .../Integration/Icingadb/IcingadbBackend.php | 22 +++---------------- .../MonitoringModule/Monitoring.php | 10 ++++----- 3 files changed, 8 insertions(+), 31 deletions(-) diff --git a/library/Director/Integration/BackendInterface.php b/library/Director/Integration/BackendInterface.php index e89e1392..7b2b88c1 100644 --- a/library/Director/Integration/BackendInterface.php +++ b/library/Director/Integration/BackendInterface.php @@ -6,13 +6,6 @@ use Icinga\Web\Url; interface BackendInterface { - /** - * Whether the backend is available - * - * @return bool - */ - public function isAvailable(): bool; - /** * Whether the backend has the given host * diff --git a/library/Director/Integration/Icingadb/IcingadbBackend.php b/library/Director/Integration/Icingadb/IcingadbBackend.php index 532c537f..874cddde 100644 --- a/library/Director/Integration/Icingadb/IcingadbBackend.php +++ b/library/Director/Integration/Icingadb/IcingadbBackend.php @@ -2,7 +2,6 @@ namespace Icinga\Module\Director\Integration\Icingadb; -use Icinga\Application\Modules\Module; use Icinga\Module\Director\Auth\Permission; use Icinga\Module\Director\Auth\Restriction; use Icinga\Module\Director\Integration\BackendInterface; @@ -19,22 +18,9 @@ class IcingadbBackend implements BackendInterface use Database; use Auth; - /** @var bool */ - protected $isAvailable; - - public function __construct() - { - $this->isAvailable = Module::exists('icingadb'); - } - - public function isAvailable(): bool - { - return $this->isAvailable; - } - public function hasHost(?string $hostName): bool { - if ($hostName === null || ! $this->isAvailable()) { + if ($hostName === null) { return false; } @@ -43,7 +29,7 @@ class IcingadbBackend implements BackendInterface public function hasService(?string $hostName, ?string $serviceName): bool { - if ($hostName === null || $serviceName === null || ! $this->isAvailable()) { + if ($hostName === null || $serviceName === null) { return false; } @@ -52,7 +38,7 @@ class IcingadbBackend implements BackendInterface public function getHostUrl(?string $hostName): ?Url { - if ($hostName === null || ! $this->isAvailable()) { + if ($hostName === null) { return null; } @@ -62,7 +48,6 @@ class IcingadbBackend implements BackendInterface public function canModifyHost(?string $hostName): bool { if ($hostName === null - || ! $this->isAvailable() || ! $this->getAuth()->hasPermission(Permission::ICINGADB_HOSTS) ) { return false; @@ -77,7 +62,6 @@ class IcingadbBackend implements BackendInterface { if ($hostName === null || $serviceName === null - || ! $this->isAvailable() || ! $this->getAuth()->hasPermission(Permission::ICINGADB_SERVICES) ) { return false; diff --git a/library/Director/Integration/MonitoringModule/Monitoring.php b/library/Director/Integration/MonitoringModule/Monitoring.php index cb574feb..5a2dfde8 100644 --- a/library/Director/Integration/MonitoringModule/Monitoring.php +++ b/library/Director/Integration/MonitoringModule/Monitoring.php @@ -28,11 +28,6 @@ class Monitoring implements BackendInterface $this->initializeMonitoringBackend(); } - public function isAvailable(): bool - { - return $this->backend !== null; - } - public function getHostUrl(?string $hostName): ?Url { if ($hostName === null) { @@ -197,4 +192,9 @@ class Monitoring implements BackendInterface } } } + + protected function isAvailable(): bool + { + return $this->backend !== null; + } }