Skip to content

Commit

Permalink
Monitoring, various: use monitoring permissions
Browse files Browse the repository at this point in the history
fixes #2304
  • Loading branch information
Thomas-Gelf committed Mar 18, 2021
1 parent 2909746 commit c27d9c7
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 20 deletions.
57 changes: 51 additions & 6 deletions application/controllers/HostController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Icinga\Module\Director\Controllers;

use gipfl\Web\Widget\Hint;
use Icinga\Module\Director\Monitoring;
use ipl\Html\Html;
use gipfl\IcingaWeb2\Link;
use gipfl\IcingaWeb2\Url;
Expand Down Expand Up @@ -30,15 +31,59 @@ class HostController extends ObjectController
{
protected function checkDirectorPermissions()
{
if (in_array($this->getRequest()->getActionName(), [
if ($this->isServiceAction() && (new Monitoring())->authCanEditService(
$this->Auth(),
$this->getParam('name'),
$this->getParam('service')
)) {
return;
}

if ($this->isServicesReadOnlyAction()) {
$this->assertPermission('director/monitoring/services-ro');
return;
}

if ($this->hasPermission('director/hosts')) { // faster
return;
}

if ($this->canModifyHostViaMonitoringPermissions($this->getParam('name'))) {
return;
}

$this->assertPermission('director/hosts'); // complain about default hosts permission
}

protected function isServicesReadOnlyAction()
{
return in_array($this->getRequest()->getActionName(), [
'servicesro',
'findservice',
'invalidservice'
])) {
$this->assertPermission('director/monitoring/services-ro');
} else {
$this->assertPermission('director/hosts');
'invalidservice',
]);
}

protected function isServiceAction()
{
return in_array($this->getRequest()->getActionName(), [
'servicesro',
'findservice',
'invalidservice',
'servicesetservice',
'appliedservice',
'inheritedservice',
]);
}

protected function canModifyHostViaMonitoringPermissions($hostname)
{
if ($this->hasPermission('director/monitoring/hosts')) {
$monitoring = new Monitoring();
return $monitoring->authCanEditHost($this->Auth(), $hostname);
}

return false;
}

/**
Expand Down
5 changes: 5 additions & 0 deletions application/controllers/ServiceController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Exception;
use Icinga\Module\Director\Forms\IcingaServiceForm;
use Icinga\Module\Director\Monitoring;
use Icinga\Module\Director\Web\Controller\ObjectController;
use Icinga\Module\Director\Objects\IcingaServiceSet;
use Icinga\Module\Director\Objects\IcingaService;
Expand All @@ -25,6 +26,10 @@ class ServiceController extends ObjectController

protected function checkDirectorPermissions()
{
if ($this->hasPermission('director/monitoring/services')) {
$monitoring = new Monitoring();
return $monitoring->authCanEditService($this->Auth(), $this->getParam('host'), $this->getParam('name'));
}
$this->assertPermission('director/hosts');
}

Expand Down
16 changes: 16 additions & 0 deletions configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@
'director/monitoring/services-ro',
$this->translate('Allow readonly users to see where a Service came from')
);
$this->providePermission(
'director/monitoring/hosts',
$this->translate('Allow users to modify Hosts they are allowed to see in the monitoring module')
);
$this->providePermission(
'director/monitoring/services',
$this->translate('Allow users to modify Service they are allowed to see in the monitoring module')
);
$this->providePermission('director/*', $this->translate('Allow unrestricted access to Icinga Director'));

$this->provideRestriction(
Expand All @@ -41,6 +49,14 @@
'Limit access to the given comma-separated list of hostgroups'
)
);

$this->provideRestriction(
'director/monitoring/rw-object-filter',
$this->translate(
'Additional (monitoring module) object filter to further restrict write access'
)
);

$this->providePermission(
'director/groups-for-restricted-hosts',
$this->translate('Allow users with Hostgroup restrictions to access the Groups field')
Expand Down
3 changes: 3 additions & 0 deletions doc/82-Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ next (will be 1.9.0)
### Import and Sync
* FEATURE: introduce 'disable' as your purge action on Sync (#2285)

### Permissions and Restrictions
* FEATURE: allow using monitoring module permissions (#2304)

### User Interface
* FIX: allow switching DB config while connection is failing (#2300)
* FIX: show Override button when all Fields belong to Field Categories (#2303)
Expand Down
90 changes: 82 additions & 8 deletions library/Director/Monitoring.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
namespace Icinga\Module\Director;

use Icinga\Application\Icinga;
use Icinga\Authentication\Auth;
use Icinga\Data\Filter\Filter;
use Icinga\Module\Monitoring\Backend\MonitoringBackend;

class Monitoring
Expand All @@ -29,43 +31,115 @@ public function isAvailable()

public function hasHost($hostname)
{
return $this->backend->select()->from('hostStatus', array(
return $this->backend->select()->from('hostStatus', [
'hostname' => 'host_name',
))->where('host_name', $hostname)->fetchOne() === $hostname;
])->where('host_name', $hostname)->fetchOne() === $hostname;
}

public function hasService($hostname, $service)
{
return (array) $this->prepareServiceKeyColumnQuery($hostname, $service)->fetchRow() === [
'hostname' => $hostname,
'service' => $service,
];
}

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 ($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)
{
return $this->backend->select()->from('hostStatus', [
'hostname' => 'host_name',
])->where('host_name', $hostname)->applyFilter($filter)->fetchOne() === $hostname;
}

public function hasServiceWithExtraFilter($hostname, $service, Filter $filter)
{
return (array) $this
->prepareServiceKeyColumnQuery($hostname, $service)
->applyFilter($filter)
->fetchRow() === [
'hostname' => $hostname,
'service' => $service,
];
}

public function getHostState($hostname)
{
$hostStates = array(
$hostStates = [
'0' => 'up',
'1' => 'down',
'2' => 'unreachable',
'99' => 'pending',
);
];

$query = $this->backend->select()->from('hostStatus', array(
$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);
])->where('host_name', $hostname);

$res = $query->fetchRow();
if ($res === false) {
$res = (object) array(
$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);
}
}
14 changes: 14 additions & 0 deletions library/Director/ProvidedHook/Monitoring/HostActions.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

use Exception;
use Icinga\Application\Config;
use Icinga\Authentication\Auth;
use Icinga\Module\Director\Db;
use Icinga\Module\Director\Monitoring;
use Icinga\Module\Director\Objects\IcingaHost;
use Icinga\Module\Director\Util;
use Icinga\Module\Monitoring\Hook\HostActionsHook;
Expand Down Expand Up @@ -37,7 +39,19 @@ protected function getThem(Host $host)
);
}

$allowEdit = false;
if (Util::hasPermission('director/hosts') && IcingaHost::exists($hostname, $db)) {
$allowEdit = true;
}
$auth = Auth::getInstance();
if (Util::hasPermission('director/monitoring/hosts')) {
$monitoring = new Monitoring();
if ($monitoring->authCanEditHost($auth, $hostname)) {
$allowEdit = IcingaHost::exists($hostname, $db);
}
}

if ($allowEdit) {
$actions[mt('director', 'Modify')] = Url::fromPath(
'director/host/edit',
array('name' => $hostname)
Expand Down
17 changes: 12 additions & 5 deletions library/Director/ProvidedHook/Monitoring/ServiceActions.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

use Exception;
use Icinga\Application\Config;
use Icinga\Authentication\Auth;
use Icinga\Module\Director\Db;
use Icinga\Module\Director\Monitoring;
use Icinga\Module\Director\Objects\IcingaHost;
use Icinga\Module\Director\Util;
use Icinga\Module\Monitoring\Hook\ServiceActionsHook;
Expand Down Expand Up @@ -36,30 +38,35 @@ protected function getThem(Service $service)
}

$hostname = $service->host_name;
$serviceName = $service->service_description;
if (Util::hasPermission('director/inspect')) {
$actions[mt('director', 'Inspect')] = Url::fromPath('director/inspect/object', [
'type' => 'service',
'plural' => 'services',
'name' => sprintf(
'%s!%s',
$hostname,
$service->service_description
$serviceName
)
]);
}

$title = null;
if (Util::hasPermission('director/hosts')) {
$title = mt('director', 'Modify');
} elseif (Util::hasPermission('director/monitoring/services')) {
$monitoring = new Monitoring();
if ($monitoring->authCanEditService(Auth::getInstance(), $hostname, $serviceName)) {
$title = mt('director', 'Modify');
}
} elseif (Util::hasPermission('director/monitoring/services-ro')) {
$title = mt('director', 'Configuration');
} else {
return $actions;
}

if (IcingaHost::exists($hostname, $db)) {
if ($title && IcingaHost::exists($hostname, $db)) {
$actions[$title] = Url::fromPath('director/host/findservice', [
'name' => $hostname,
'service' => $service->service_description
'service' => $serviceName
]);
}

Expand Down
2 changes: 1 addition & 1 deletion library/Director/Web/Tabs/ObjectTabs.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ protected function addTabsForExistingObject()
]);
}

if ($object->getShortTableName() === 'host') {
if ($object->getShortTableName() === 'host' && $auth->hasPermission('director/hosts')) {
$this->add('agent', [
'url' => 'director/host/agent',
'urlParams' => $params,
Expand Down

0 comments on commit c27d9c7

Please sign in to comment.