parent
cde328eeed
commit
02a3652c86
|
@ -8,8 +8,10 @@ use Icinga\Module\Director\Db\AppliedServiceSetLoader;
|
|||
use Icinga\Module\Director\Exception\NestingError;
|
||||
use Icinga\Module\Director\IcingaConfig\AgentWizard;
|
||||
use Icinga\Module\Director\Objects\IcingaHost;
|
||||
use Icinga\Module\Director\Objects\IcingaObject;
|
||||
use Icinga\Module\Director\Objects\IcingaService;
|
||||
use Icinga\Module\Director\Objects\IcingaServiceSet;
|
||||
use Icinga\Module\Director\Restriction\BetaHostgroupRestriction;
|
||||
use Icinga\Module\Director\Util;
|
||||
use Icinga\Module\Director\Web\Controller\ObjectController;
|
||||
use Icinga\Web\Url;
|
||||
|
@ -47,6 +49,27 @@ class HostController extends ObjectController
|
|||
$this->assertPermission('director/hosts');
|
||||
}
|
||||
|
||||
protected function loadRestrictions()
|
||||
{
|
||||
return array(
|
||||
$this->getHostgroupRestriction()
|
||||
);
|
||||
}
|
||||
|
||||
protected function getHostgroupRestriction()
|
||||
{
|
||||
return new BetaHostgroupRestriction($this->db(), $this->Auth());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IcingaHost $object
|
||||
* @return bool
|
||||
*/
|
||||
protected function allowsObject(IcingaObject $object)
|
||||
{
|
||||
return $this->getHostgroupRestriction()->allowsHost($object);
|
||||
}
|
||||
|
||||
public function editAction()
|
||||
{
|
||||
parent::editAction();
|
||||
|
|
|
@ -6,6 +6,8 @@ use Icinga\Data\Filter\Filter;
|
|||
use Icinga\Data\Filter\FilterChain;
|
||||
use Icinga\Data\Filter\FilterExpression;
|
||||
use Icinga\Module\Director\Objects\IcingaHost;
|
||||
use Icinga\Module\Director\Restriction\BetaHostgroupRestriction;
|
||||
use Icinga\Module\Director\Tables\IcingaHostTable;
|
||||
use Icinga\Module\Director\Web\Controller\ObjectsController;
|
||||
|
||||
class HostsController extends ObjectsController
|
||||
|
@ -76,4 +78,14 @@ class HostsController extends ObjectsController
|
|||
|
||||
$this->setViewScript('objects/form');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IcingaHostTable $table
|
||||
*/
|
||||
protected function applyTableFilters($table)
|
||||
{
|
||||
$table->addObjectRestriction(
|
||||
new BetaHostgroupRestriction($this->db(), $this->Auth())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Icinga\Module\Director\Forms;
|
||||
|
||||
use Icinga\Module\Director\Restriction\BetaHostgroupRestriction;
|
||||
use Icinga\Module\Director\Web\Form\DirectorObjectForm;
|
||||
|
||||
class IcingaHostForm extends DirectorObjectForm
|
||||
|
@ -132,6 +133,10 @@ class IcingaHostForm extends DirectorObjectForm
|
|||
*/
|
||||
protected function addGroupsElement()
|
||||
{
|
||||
if ($this->hasHostGroupRestriction()) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$groups = $this->enumHostgroups();
|
||||
if (empty($groups)) {
|
||||
return $this;
|
||||
|
@ -153,6 +158,19 @@ class IcingaHostForm extends DirectorObjectForm
|
|||
return $this;
|
||||
}
|
||||
|
||||
protected function hasHostGroupRestriction()
|
||||
{
|
||||
foreach ($this->getObjectRestrictions() as $restriction) {
|
||||
if ($restriction instanceof BetaHostgroupRestriction) {
|
||||
if ($restriction->isRestricted()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
|
|
|
@ -2,16 +2,25 @@
|
|||
|
||||
namespace Icinga\Module\Director\Tables;
|
||||
|
||||
use Icinga\Module\Director\Restriction\ObjectRestriction;
|
||||
use Icinga\Module\Director\Web\Table\QuickTable;
|
||||
|
||||
class IcingaHostTable extends QuickTable
|
||||
{
|
||||
protected $objectRestrictions = array();
|
||||
|
||||
protected $searchColumns = array(
|
||||
'host',
|
||||
'address',
|
||||
'display_name'
|
||||
);
|
||||
|
||||
public function addObjectRestriction(ObjectRestriction $restriction)
|
||||
{
|
||||
$this->objectRestrictions[$restriction->getName()] = $restriction;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getColumns()
|
||||
{
|
||||
return array(
|
||||
|
@ -58,10 +67,16 @@ class IcingaHostTable extends QuickTable
|
|||
|
||||
protected function getUnfilteredQuery()
|
||||
{
|
||||
return $this->db()->select()->from(
|
||||
$query = $this->db()->select()->from(
|
||||
array('h' => 'icinga_host'),
|
||||
array()
|
||||
)->order('h.object_name');
|
||||
|
||||
foreach ($this->objectRestrictions as $restriction) {
|
||||
$restriction->applyToHostsQuery($query);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function getBaseQuery()
|
||||
|
|
|
@ -18,6 +18,14 @@ $this->providePermission(
|
|||
);
|
||||
$this->providePermission('director/*', $this->translate('Allow unrestricted access to Icinga Director'));
|
||||
|
||||
$this->provideRestriction(
|
||||
'director/beta-filter/hostgroups',
|
||||
$this->translate(
|
||||
'BETA: Limit access to the given comma-separated list of hostgroups. This'
|
||||
. ' restriction might change without pre-announcement'
|
||||
)
|
||||
);
|
||||
|
||||
$this->provideSearchUrl($this->translate('Host configs'), 'director/hosts?limit=10', 60);
|
||||
|
||||
/*
|
||||
|
|
|
@ -4,7 +4,9 @@ namespace Icinga\Module\Director\Dashboard;
|
|||
|
||||
use Countable;
|
||||
use Exception;
|
||||
use Icinga\Authentication\Auth;
|
||||
use Icinga\Module\Director\Objects\IcingaObject;
|
||||
use Icinga\Module\Director\Restriction\BetaHostgroupRestriction;
|
||||
use Icinga\Web\View;
|
||||
use Icinga\Module\Director\Dashboard\Dashlet\Dashlet;
|
||||
use Icinga\Module\Director\Db;
|
||||
|
@ -183,10 +185,40 @@ abstract class Dashboard implements Countable
|
|||
}
|
||||
}
|
||||
|
||||
return $this->db->getDbAdapter()->select()->from(
|
||||
$query = $this->db->getDbAdapter()->select()->from(
|
||||
array('o' => 'icinga_' . $type),
|
||||
$columns
|
||||
);
|
||||
|
||||
return $this->applyRestrictions($type, $query);
|
||||
}
|
||||
|
||||
protected function applyRestrictions($type, $query)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'hostgroup':
|
||||
$r = new BetaHostgroupRestriction($this->getDb(), $this->getAuth());
|
||||
$r->applyToHostGroupsQuery($query);
|
||||
break;
|
||||
case 'host':
|
||||
$r = new BetaHostgroupRestriction($this->getDb(), $this->getAuth());
|
||||
$r->applyToHostsQuery($query, 'o.id');
|
||||
break;
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function applyHostgroupRestrictions($query)
|
||||
{
|
||||
$restrictions = new BetaHostgroupRestriction($this->getDb(), $this->getAuth());
|
||||
$restrictions->applyToHostGroupsQuery($query);
|
||||
|
||||
}
|
||||
|
||||
protected function getAuth()
|
||||
{
|
||||
return Auth::getInstance();
|
||||
}
|
||||
|
||||
protected function getCntSql($objectType)
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
namespace Icinga\Module\Director\Restriction;
|
||||
|
||||
use Icinga\Module\Director\Objects\IcingaHost;
|
||||
use Zend_Db_Select as ZfSelect;
|
||||
|
||||
class BetaHostgroupRestriction extends ObjectRestriction
|
||||
{
|
||||
protected $name = 'director/beta-filter/hostgroups';
|
||||
|
||||
public function allowsHost(IcingaHost $host)
|
||||
{
|
||||
if (! $this->isRestricted()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$query = $this->db->select()->from(
|
||||
array('h' => 'icinga_host'),
|
||||
array('id')
|
||||
);
|
||||
|
||||
$this->applyToHostsQuery($query);
|
||||
|
||||
return (int) $this->db->fetchOne($query) === (int) $host->get('id');
|
||||
}
|
||||
|
||||
public function applyToHostsQuery(ZfSelect $query, $hostIdColumn = 'h.id')
|
||||
{
|
||||
if (! $this->isRestricted()) {
|
||||
return;
|
||||
}
|
||||
$groups = $this->listRestrictedHostgroups();
|
||||
|
||||
if (empty($groups)) {
|
||||
$query->where('(1 = 0)');
|
||||
} else {
|
||||
$sub = $this->db->select()->from(
|
||||
array('hgh' => 'icinga_hostgroup_host'),
|
||||
array('e' => '(1)')
|
||||
)->join(
|
||||
array('hg' => 'icinga_hostgroup'),
|
||||
'hgh.hostgroup_id = hg.id'
|
||||
)->where('hgh.host_id = ' . $hostIdColumn)
|
||||
->where('hg.object_name IN (?)', $groups);
|
||||
|
||||
$query->where('EXISTS ?', $sub);
|
||||
}
|
||||
}
|
||||
|
||||
public function applyToHostGroupsQuery(ZfSelect $query)
|
||||
{
|
||||
if (! $this->isRestricted()) {
|
||||
return;
|
||||
}
|
||||
$groups = $this->listRestrictedHostgroups();
|
||||
|
||||
if (empty($groups)) {
|
||||
$query->where('(1 = 0)');
|
||||
} else {
|
||||
$query->where('object_name IN (?)', $groups);
|
||||
}
|
||||
}
|
||||
|
||||
protected function listRestrictedHostgroups()
|
||||
{
|
||||
if ($restrictions = $this->auth->getRestrictions($this->getName())) {
|
||||
$groups = array();
|
||||
foreach ($restrictions as $restriction) {
|
||||
foreach ($this->gracefullySplitOnComma($restriction) as $group) {
|
||||
$groups[$group] = $group;
|
||||
}
|
||||
}
|
||||
|
||||
return array_keys($groups);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
namespace Icinga\Module\Director\Restriction;
|
||||
|
||||
use Icinga\Authentication\Auth;
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
use Icinga\Module\Director\Db;
|
||||
|
||||
class ObjectRestriction
|
||||
{
|
||||
/** @var string */
|
||||
protected $name;
|
||||
|
||||
/** @var \Zend_Db_Adapter_Abstract */
|
||||
protected $db;
|
||||
|
||||
/** @var Auth */
|
||||
protected $auth;
|
||||
|
||||
public function __construct(Db $connection, Auth $auth)
|
||||
{
|
||||
$this->db = $connection->getDbAdapter();
|
||||
$this->auth = $auth;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
if ($this->name === null) {
|
||||
throw new ProgrammingError('ObjectRestriction has no name');
|
||||
}
|
||||
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function isRestricted()
|
||||
{
|
||||
$restrictions = $this->auth->getRestrictions($this->getName());
|
||||
return ! empty($restrictions);
|
||||
}
|
||||
|
||||
protected function gracefullySplitOnComma($string)
|
||||
{
|
||||
return preg_split('/\s*,\s*/', $string, -1, PREG_SPLIT_NO_EMPTY);
|
||||
}
|
||||
}
|
|
@ -22,6 +22,16 @@ abstract class ObjectController extends ActionController
|
|||
'endpoint'
|
||||
);
|
||||
|
||||
protected function loadRestrictions()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
protected function allowsObject(IcingaObject $object)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
|
@ -169,6 +179,7 @@ abstract class ObjectController extends ActionController
|
|||
->setDb($this->db())
|
||||
->setApi($this->getApiIfAvailable());
|
||||
$form->setObject($object);
|
||||
$form->setObjectRestrictions($this->loadRestrictions());
|
||||
|
||||
$this->view->title = $object->object_name;
|
||||
$this->view->form->handleRequest();
|
||||
|
@ -334,6 +345,11 @@ abstract class ObjectController extends ActionController
|
|||
$name,
|
||||
$this->db()
|
||||
);
|
||||
|
||||
if (! $this->allowsObject($this->object)) {
|
||||
$this->object = null;
|
||||
throw new NotFoundError('No such object available');
|
||||
}
|
||||
} elseif ($id = $this->params->get('id')) {
|
||||
$this->object = IcingaObject::loadByType(
|
||||
$this->getType(),
|
||||
|
|
|
@ -142,6 +142,8 @@ abstract class ObjectsController extends ActionController
|
|||
}
|
||||
}
|
||||
|
||||
$this->applyTableFilters($table);
|
||||
|
||||
$this->view->title = $title;
|
||||
|
||||
$this->view->addLink = $this->view->qlink(
|
||||
|
@ -155,6 +157,10 @@ abstract class ObjectsController extends ActionController
|
|||
$this->setViewScript('objects/table');
|
||||
}
|
||||
|
||||
protected function applyTableFilters($table)
|
||||
{
|
||||
}
|
||||
|
||||
public function editAction()
|
||||
{
|
||||
$type = ucfirst($this->getType());
|
||||
|
|
|
@ -11,6 +11,7 @@ use Icinga\Module\Director\Exception\NestingError;
|
|||
use Icinga\Module\Director\IcingaConfig\StateFilterSet;
|
||||
use Icinga\Module\Director\IcingaConfig\TypeFilterSet;
|
||||
use Icinga\Module\Director\Objects\IcingaObject;
|
||||
use Icinga\Module\Director\Restriction\ObjectRestriction;
|
||||
use Icinga\Module\Director\Util;
|
||||
use Zend_Form_Element as ZfElement;
|
||||
use Zend_Form_Element_Select as ZfSelect;
|
||||
|
@ -49,6 +50,9 @@ abstract class DirectorObjectForm extends QuickForm
|
|||
|
||||
private $presetImports;
|
||||
|
||||
/** @var ObjectRestriction[] */
|
||||
private $objectRestrictions = array();
|
||||
|
||||
private $earlyProperties = array(
|
||||
'imports',
|
||||
'check_command',
|
||||
|
@ -561,6 +565,38 @@ abstract class DirectorObjectForm extends QuickForm
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ObjectRestriction[] $restrictions
|
||||
* @return $this
|
||||
*/
|
||||
public function setObjectRestrictions(array $restrictions)
|
||||
{
|
||||
$this->objectRestrictions = array();
|
||||
foreach ($restrictions as $restriction) {
|
||||
$this->addObjectRestriction($restriction);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ObjectRestriction $restriction
|
||||
* @return $this
|
||||
*/
|
||||
public function addObjectRestriction(ObjectRestriction $restriction)
|
||||
{
|
||||
$this->objectRestrictions[$restriction->getName()] = $restriction;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ObjectRestriction[]
|
||||
*/
|
||||
public function getObjectRestrictions()
|
||||
{
|
||||
return $this->objectRestrictions;
|
||||
}
|
||||
|
||||
protected function getObjectClassname()
|
||||
{
|
||||
if ($this->className === null) {
|
||||
|
|
Loading…
Reference in New Issue