permissions: provide new ones and enforce them

fixes #13039
This commit is contained in:
Thomas Gelf 2016-11-03 16:06:18 +01:00
parent 7e4479a76a
commit b2c834e7a4
30 changed files with 276 additions and 91 deletions

View File

@ -15,8 +15,13 @@ class ConfigController extends ActionController
{
protected $isApified = true;
protected function checkDirectorPermissions()
{
}
public function deploymentsAction()
{
$this->assertPermission('director/deploy');
$this->setAutorefreshInterval(5);
try {
if ($this->db()->hasUncollectedDeployments()) {
@ -49,6 +54,8 @@ class ConfigController extends ActionController
public function deployAction()
{
$this->assertPermission('director/deploy');
// TODO: require POST
$isApiRequest = $this->getRequest()->isApiRequest();
$checksum = $this->params->get('checksum');
@ -86,23 +93,29 @@ class ConfigController extends ActionController
public function activitiesAction()
{
$this->assertPermission('director/audit');
$this->setAutorefreshInterval(10);
$this->overviewTabs()->activate('activitylog');
$this->view->title = $this->translate('Activity Log');
$lastDeployedId = $this->db()->getLastDeploymentActivityLogId();
$this->prepareTable('activityLog');
$this->view->table->setLastDeployedId($lastDeployedId);
$this->view->form = $this
->loadForm('DeployConfig')
->setDb($this->db())
->setApi($this->api())
->handleRequest();
if ($this->hasPermission('director/deploy')) {
$this->view->form = $this
->loadForm('DeployConfig')
->setDb($this->db())
->setApi($this->api())
->handleRequest();
}
$this->setViewScript('list/table');
}
public function settingsAction()
{
$this->assertPermission('director/admin');
$this->overviewTabs()->activate('settings');
$this->view->title = $this->translate('Settings');
$this->view->form = $this
@ -116,6 +129,8 @@ class ConfigController extends ActionController
// Show all files for a given config
public function filesAction()
{
$this->assertPermission('director/showconfig');
$this->setAutorefreshInterval(10);
$this->view->title = $this->translate('Generated config');
$tabs = $this->getTabs();
@ -163,6 +178,8 @@ class ConfigController extends ActionController
// Show a single file
public function fileAction()
{
$this->assertPermission('director/showconfig');
$fileOnly = $this->params->get('fileOnly');
$this->view->highlight = $this->params->get('highlight');
$this->view->highlightSeverity = $this->params->get('highlightSeverity');
@ -196,6 +213,8 @@ class ConfigController extends ActionController
public function showAction()
{
$this->assertPermission('director/showconfig');
$this->configTabs()->activate('config');
$this->view->config = IcingaConfig::load(Util::hex2binary($this->params->get('checksum')), $this->db());
}
@ -214,6 +233,8 @@ class ConfigController extends ActionController
public function diffAction()
{
$this->assertPermission('director/showconfig');
$db = $this->db();
$this->view->title = $this->translate('Config diff');
@ -248,6 +269,8 @@ class ConfigController extends ActionController
public function filediffAction()
{
$this->assertPermission('director/showconfig');
$db = $this->db();
$leftSum = $this->params->get('left');
$rightSum = $this->params->get('right');
@ -271,25 +294,36 @@ class ConfigController extends ActionController
protected function overviewTabs()
{
$this->view->tabs = $this->getTabs()->add(
'activitylog',
array(
'label' => $this->translate('Activity Log'),
'url' => 'director/config/activities'
)
)->add(
'deploymentlog',
array(
'label' => $this->translate('Deployments'),
'url' => 'director/config/deployments'
)
)->add(
'settings',
array(
'label' => $this->translate('Settings'),
'url' => 'director/config/settings'
)
);
$this->view->tabs = $tabs = $this->getTabs();
if ($this->hasPermission('director/audit')) {
$tabs->add(
'activitylog',
array(
'label' => $this->translate('Activity Log'),
'url' => 'director/config/activities'
)
);
}
if ($this->hasPermission('director/deploy')) {
$tabs->add(
'deploymentlog',
array(
'label' => $this->translate('Deployments'),
'url' => 'director/config/deployments'
)
);
}
if ($this->hasPermission('director/admin')) {
$tabs->add(
'settings',
array(
'label' => $this->translate('Settings'),
'url' => 'director/config/settings'
)
);
}
return $this->view->tabs;
}
@ -297,7 +331,7 @@ class ConfigController extends ActionController
{
$tabs = $this->getTabs();
if ($deploymentId = $this->params->get('deployment_id')) {
if ($this->hasPermission('director/deploy') && $deploymentId = $this->params->get('deployment_id')) {
$tabs->add('deployment', array(
'label' => $this->translate('Deployment'),
'url' => 'director/deployment/show',
@ -307,11 +341,13 @@ class ConfigController extends ActionController
));
}
$tabs->add('config', array(
'label' => $this->translate('Config'),
'url' => 'director/config/files',
'urlParams' => $this->getConfigTabParams()
));
if ($this->hasPermission('director/showconfig')) {
$tabs->add('config', array(
'label' => $this->translate('Config'),
'url' => 'director/config/files',
'urlParams' => $this->getConfigTabParams()
));
}
return $tabs;
}

View File

@ -9,6 +9,10 @@ use Icinga\Module\Director\Web\Controller\ActionController;
class DashboardController extends ActionController
{
protected function checkDirectorPermissions()
{
}
public function indexAction()
{
if ($this->getRequest()->isGet()) {

View File

@ -9,6 +9,11 @@ use Icinga\Module\Director\Util;
class DeploymentController extends ActionController
{
protected function checkDirectorPermissions()
{
$this->assertPermission('director/deploy');
}
public function indexAction()
{
$this->view->title = $this->translate('Deployment details');

View File

@ -41,6 +41,11 @@ class HostController extends ObjectController
}
}
protected function checkDirectorPermissions()
{
$this->assertPermission('director/hosts');
}
public function editAction()
{
parent::editAction();

View File

@ -10,4 +10,9 @@ class HostsController extends ObjectsController
'imports',
'groups'
);
protected function checkDirectorPermissions()
{
$this->assertPermission('director/hosts');
}
}

View File

@ -6,10 +6,9 @@ use Icinga\Module\Director\Web\Controller\ActionController;
class InspectController extends ActionController
{
public function init()
protected function checkDirectorPermissions()
{
$this->assertPermission('director/inspect');
parent::init();
}
public function typesAction()

View File

@ -9,6 +9,11 @@ use Icinga\Module\Director\Objects\IcingaService;
class NotificationController extends ObjectController
{
protected function checkDirectorPermissions()
{
$this->assertPermission('director/notifications');
}
public function init()
{
parent::init();

View File

@ -6,4 +6,8 @@ use Icinga\Module\Director\Web\Controller\ObjectsController;
class NotificationsController extends ObjectsController
{
protected function checkDirectorPermissions()
{
$this->assertPermission('director/notifications');
}
}

View File

@ -27,6 +27,11 @@ class ServiceController extends ObjectController
}
}
protected function checkDirectorPermissions()
{
$this->assertPermission('director/hosts');
}
public function init()
{
if ($host = $this->params->get('host')) {

View File

@ -15,6 +15,11 @@ class ShowController extends ActionController
protected $oldObject;
protected function checkDirectorPermissions()
{
$this->assertPermission('director/showconfig');
}
protected function objectKey($entry)
{
if ($entry->object_type === 'icinga_service' || $entry->object_type === 'icinga_service_set') {

View File

@ -6,4 +6,8 @@ use Icinga\Module\Director\Web\Controller\ObjectController;
class UserController extends ObjectController
{
protected function checkDirectorPermissions()
{
$this->assertPermission('director/users');
}
}

View File

@ -6,4 +6,8 @@ use Icinga\Module\Director\Web\Controller\ObjectsController;
class UsersController extends ObjectsController
{
protected function checkDirectorPermissions()
{
$this->assertPermission('director/users');
}
}

View File

@ -2,6 +2,7 @@
namespace Icinga\Module\Director\Tables;
use Icinga\Module\Director\Util;
use Icinga\Module\Director\Web\Table\QuickTable;
class ActivityLogTable extends QuickTable
@ -41,7 +42,11 @@ class ActivityLogTable extends QuickTable
protected function listTableClasses()
{
return array_merge(array('activity-log'), parent::listTableClasses());
if (Util::hasPermission('director/showconfig')) {
return array_merge(array('activity-log'), parent::listTableClasses());
} else {
return array('simple', 'common-table', 'activity-log');
}
}
public function render()
@ -75,10 +80,15 @@ class ActivityLogTable extends QuickTable
protected function getActionUrl($row)
{
return $this->url(
'director/show/activitylog',
array_merge(array('id' => $row->id), $this->extraParams)
);
if (Util::hasPermission('director/showconfig')) {
return $this->url(
'director/show/activitylog',
array_merge(array('id' => $row->id), $this->extraParams)
);
} else {
return false;
}
}
public function getTitles()

View File

@ -4,6 +4,10 @@ if (! $this->undeployedChanges && ! $this->totalUndeployedChanges) {
return;
}
if (! $this->hasPermission('director/deploy')) {
return;
}
if ($this->undeployedChanges === 0) {
if ($this->totalUndeployedChanges) {
$msg = $this->translate('The is a single pending change');

View File

@ -1,11 +1,13 @@
<?php
$this->providePermission('director/api', $this->translate('Allow to access the director API'));
$this->providePermission('director/hosts/read', $this->translate('Allow to configure hosts'));
$this->providePermission('director/hosts/write', $this->translate('Allow to configure hosts'));
$this->providePermission('director/inspect', $this->translate('Allow to inspect objects through the Icinga 2 API'));
$this->providePermission('director/templates/read', $this->translate('Allow to see template details'));
$this->providePermission('director/templates/write', $this->translate('Allow to configure templates'));
$this->providePermission('director/audit', $this->translate('Allow to access the full audit log'));
$this->providePermission('director/showconfig', $this->translate('Allow to show configuration (could contain sensitive information)'));
$this->providePermission('director/deploy', $this->translate('Allow to deploy configuration'));
$this->providePermission('director/hosts', $this->translate('Allow to configure hosts'));
$this->providePermission('director/users', $this->translate('Allow to configure users'));
$this->providePermission('director/notifications', $this->translate('Allow to configure notifications'));
$this->providePermission('director/inspect', $this->translate('Allow to inspect objects through the Icinga 2 API (could contain sensitive information)'));
$this->provideSearchUrl($this->translate('Host configs'), 'director/hosts?limit=10', 60);
@ -33,14 +35,32 @@ $section = $this->menuSection(
'state' => 'critical'
));
$section->add($this->translate('Hosts'))->setUrl('director/hosts')->setPriority(30);
$section->add($this->translate('Services'))->setUrl('director/services/templates')->setPriority(40);
$section->add($this->translate('Commands'))->setUrl('director/commands')->setPriority(50);
$section->add($this->translate('Users'))->setUrl('director/users')->setPriority(70);
$section->add($this->translate('Automation'))
$section->add(N_('Hosts'))
->setUrl('director/hosts')
->setPermission('director/hosts')
->setPriority(30);
$section->add(N_('Services'))
->setUrl('director/services/templates')
->setPermission('director/admin')
->setPriority(40);
$section->add(N_('Commands'))
->setUrl('director/commands')
->setPermission('director/admin')
->setPriority(50);
$section->add(N_('Users'))
->setUrl('director/users')
->setPermission('director/users')
->setPriority(70);
$section->add(N_('Automation'))
->setUrl('director/list/importsource')
->setPermission('director/admin')
->setPriority(901);
$section->add($this->translate('Config history'))
$section->add(N_('Activity log'))
->setUrl('director/config/activities')
->setPriority(902)
->setPermission('director/audit')
->setRenderer('ConfigHealthItemRenderer');
$section->add(N_('Deployments'))
->setUrl('director/config/deployments')
->setPriority(902)
->setPermission('director/deployments');

View File

@ -30,6 +30,6 @@ class ActivityLogDashlet extends Dashlet
public function listRequiredPermissions()
{
return array('director/activitylog');
return array('director/audit');
}
}

View File

@ -15,6 +15,6 @@ class ApiUserObjectDashlet extends Dashlet
public function getUrl()
{
return 'director/apiusers';
return 'director/admin';
}
}

View File

@ -15,6 +15,6 @@ class CommandObjectDashlet extends Dashlet
public function getUrl()
{
return 'director/commands';
return 'director/admin';
}
}

View File

@ -25,6 +25,6 @@ class DatafieldDashlet extends Dashlet
public function listRequiredPermissions()
{
return array('director/data');
return array('director/admin');
}
}

View File

@ -25,6 +25,6 @@ class DatalistDashlet extends Dashlet
public function listRequiredPermissions()
{
return array('director/data');
return array('director/admin');
}
}

View File

@ -22,6 +22,11 @@ class EndpointObjectDashlet extends Dashlet
return 'director/endpoints';
}
public function listRequiredPermissions()
{
return array('director/admin');
}
protected function hasDeploymentEndpoint()
{
if ($this->hasDeploymentEndpoint === null) {

View File

@ -60,6 +60,6 @@ class ImportSourceDashlet extends Dashlet
public function listRequiredPermissions()
{
return array('director/sync');
return array('director/admin');
}
}

View File

@ -57,4 +57,9 @@ class JobDashlet extends Dashlet
{
return 'director/jobs';
}
public function listRequiredPermissions()
{
return array('director/admin');
}
}

View File

@ -17,4 +17,9 @@ class ServiceObjectDashlet extends Dashlet
{
return 'director/services';
}
public function listRequiredPermissions()
{
return array('director/admin');
}
}

View File

@ -60,6 +60,6 @@ class SyncDashlet extends Dashlet
public function listRequiredPermissions()
{
return array('director/sync');
return array('director/admin');
}
}

View File

@ -20,4 +20,9 @@ class TimeperiodObjectDashlet extends Dashlet
{
return 'director/timeperiods';
}
public function listRequiredPermissions()
{
return array('director/admin');
}
}

View File

@ -17,4 +17,9 @@ class ZoneObjectDashlet extends Dashlet
{
return 'director/zones';
}
public function listRequiredPermissions()
{
return array('director/admin');
}
}

View File

@ -13,9 +13,9 @@ use Icinga\Module\Director\Monitoring;
use Icinga\Module\Director\Objects\IcingaEndpoint;
use Icinga\Module\Director\Web\Form\FormLoader;
use Icinga\Module\Director\Web\Form\QuickBaseForm;
use Icinga\Module\Director\Web\Form\QuickForm;
use Icinga\Module\Director\Web\Table\QuickTable;
use Icinga\Module\Director\Web\Table\TableLoader;
use Icinga\Security\SecurityException;
use Icinga\Web\Controller;
use Icinga\Web\Widget;
@ -45,6 +45,35 @@ abstract class ActionController extends Controller
throw new NotFoundError('No such API endpoint found');
}
}
$this->checkDirectorPermissions();
}
protected function checkDirectorPermissions()
{
$this->assertPermission('director/admin');
}
/**
* Assert that the current user has one of the given permission
*
* @param array $permissions Permission name list
*
* @throws SecurityException If the current user lacks the given permission
*/
protected function assertOneOfPermissions($permissions)
{
$auth = $this->Auth();
foreach ($permissions as $permission)
if ($auth->hasPermission($permission)) {
return;
}
throw new SecurityException(
'Got none of the following permissions: %s',
implode(', ', $permissions)
);
}
protected function isApified()

View File

@ -44,17 +44,24 @@ abstract class ObjectController extends ActionController
));
}
$tabs->add('render', array(
'url' => sprintf('director/%s/render', $type),
'urlParams' => $params,
'label' => $this->translate('Preview'),
))->add('history', array(
'url' => sprintf('director/%s/history', $type),
'urlParams' => $params,
'label' => $this->translate('History')
));
if ($this->hasPermission('director/showconfig')) {
$tabs->add('render', array(
'url' => sprintf('director/%s/render', $type),
'urlParams' => $params,
'label' => $this->translate('Preview'),
));
}
if ($this->hasFields()) {
if ($this->hasPermission('director/audit')) {
$tabs->add('history', array(
'url' => sprintf('director/%s/history', $type),
'urlParams' => $params,
'label' => $this->translate('History')
));
}
if ($this->hasPermission('director/admin') && $this->hasFields()) {
$tabs->add('fields', array(
'url' => sprintf('director/%s/fields', $type),
'urlParams' => $params,
@ -99,6 +106,7 @@ abstract class ObjectController extends ActionController
public function renderAction()
{
$this->assertPermission('director/showconfig');
$type = $this->getType();
$this->getTabs()->activate('render');
$object = $this->object;
@ -237,6 +245,7 @@ abstract class ObjectController extends ActionController
public function fieldsAction()
{
$this->hasPermission('director/admin');
$object = $this->object;
$type = $this->getType();
@ -278,6 +287,7 @@ abstract class ObjectController extends ActionController
public function historyAction()
{
$this->hasPermission('director/audit');
$this->setAutorefreshInterval(10);
$db = $this->db();
$type = $this->getType();

View File

@ -54,32 +54,36 @@ abstract class ObjectsController extends ActionController
'url' => sprintf('director/%ss', strtolower($type)),
'label' => $this->translate(ucfirst($type) . 's'),
));
if ($object->supportsImports()) {
$tabs->add('templates', array(
'url' => sprintf('director/%ss/templates', strtolower($type)),
'label' => $this->translate('Templates'),
));
}
if ($object->supportsGroups() || $object->isGroup()) {
$tabs->add('objectgroups', array(
'url' => sprintf('director/%sgroups', $type),
'label' => $this->translate('Groups')
));
}
if ($object->supportsSets() || $object->isGroup() /** Bullshit, need base object, wrong on users */) {
/** forced to master, disabled for now
$tabs->add('sets', array(
'url' => sprintf('director/%ss/sets', $type),
'label' => $this->translate('Sets')
));
*/
}
if ($this->hasPermission('director/admin')) {
if ($object->supportsImports()) {
$tabs->add('templates', array(
'url' => sprintf('director/%ss/templates', strtolower($type)),
'label' => $this->translate('Templates'),
));
}
$tabs->add('tree', array(
'url' => sprintf('director/%ss/templatetree', $type),
'label' => $this->translate('Tree'),
));
if ($object->supportsGroups() || $object->isGroup()) {
$tabs->add('objectgroups', array(
'url' => sprintf('director/%sgroups', $type),
'label' => $this->translate('Groups')
));
}
if ($object->supportsSets() || $object->isGroup() /** Bullshit, need base object, wrong on users */) {
/** forced to master, disabled for now
$tabs->add('sets', array(
'url' => sprintf('director/%ss/sets', $type),
'label' => $this->translate('Sets')
));
*/
}
$tabs->add('tree', array(
'url' => sprintf('director/%ss/templatetree', $type),
'label' => $this->translate('Tree'),
));
}
}
public function indexAction()
@ -90,7 +94,6 @@ abstract class ObjectsController extends ActionController
$type = $this->getType();
$ltype = strtolower($type);
$this->assertPermission('director/' . $type . 's/read');
/** @var IcingaObject $dummy */
$dummy = $this->dummyObject();
@ -243,11 +246,13 @@ abstract class ObjectsController extends ActionController
public function templatesAction()
{
$this->assertPermission('director/admin');
$this->indexAction();
}
public function templatetreeAction()
{
$this->assertPermission('director/admin');
$this->setAutorefreshInterval(10);
$this->getTabs()->activate('tree');
$this->view->tree = $this->db()->fetchTemplateTree(strtolower($this->getType()));
@ -257,6 +262,7 @@ abstract class ObjectsController extends ActionController
public function setsAction()
{
$this->assertPermission('director/admin');
$this->view->title = $this->translate('Service sets');
$this->view->table = $this
->loadTable('IcingaServiceSet')