From 0124a33037600eed7c4fc8ec99dbc3a148774b5c Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 31 Oct 2014 11:20:17 +0100 Subject: [PATCH 01/36] Add method Config::isEmpty() --- library/Icinga/Application/Config.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/library/Icinga/Application/Config.php b/library/Icinga/Application/Config.php index c7998a0bb..ca377c10a 100644 --- a/library/Icinga/Application/Config.php +++ b/library/Icinga/Application/Config.php @@ -167,4 +167,14 @@ class Config extends Zend_Config { return self::$configDir . DIRECTORY_SEPARATOR . ltrim($path, DIRECTORY_SEPARATOR); } + + /** + * Is the configuration empty? + * + * @return bool + */ + public function isEmpty() + { + return empty($this->_data); + } } From e5091ec835aa89eb135a2163199a1e74a65e5473 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 31 Oct 2014 11:22:27 +0100 Subject: [PATCH 02/36] Fix Modules\Manager::getLoadedModules() PHPDoc --- library/Icinga/Application/Modules/Manager.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/library/Icinga/Application/Modules/Manager.php b/library/Icinga/Application/Modules/Manager.php index db6f0e527..36ab7dbe4 100644 --- a/library/Icinga/Application/Modules/Manager.php +++ b/library/Icinga/Application/Modules/Manager.php @@ -372,10 +372,9 @@ class Manager } /** - * Return an array containing all loaded modules + * Get the currently loaded modules * - * @return array - * @see Module + * @return Module[] */ public function getLoadedModules() { From ea1f51ad9ae9fdf6506eb286cfe035c9682033c3 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 31 Oct 2014 15:59:45 +0100 Subject: [PATCH 03/36] Use callable as type hint instead of Callback PHP 5.4 introduces callable for type hinting and PSR-5 proposes callable. --- library/Icinga/Web/Form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php index 631b2eb07..82f4501a1 100644 --- a/library/Icinga/Web/Form.php +++ b/library/Icinga/Web/Form.php @@ -39,7 +39,7 @@ class Form extends Zend_Form /** * The callback to call instead of Form::onSuccess() * - * @var Callback + * @var callable */ protected $onSuccess; From a965017d73327385d05217f8251e197923d5c4ce Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 4 Nov 2014 14:46:56 +0100 Subject: [PATCH 04/36] INI writer: Support writing files which do not yet exist --- library/Icinga/File/Ini/IniWriter.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/Icinga/File/Ini/IniWriter.php b/library/Icinga/File/Ini/IniWriter.php index 7dc79034d..dfe588bbe 100644 --- a/library/Icinga/File/Ini/IniWriter.php +++ b/library/Icinga/File/Ini/IniWriter.php @@ -85,8 +85,10 @@ class IniWriter extends Zend_Config_Writer_FileAbstract { if (file_exists($this->_filename)) { $oldconfig = new Zend_Config_Ini($this->_filename); + $content = file_get_contents($this->_filename); } else { $oldconfig = new Zend_Config(array()); + $content = ''; } // create an internal copy of the given configuration, since the user of this class @@ -100,7 +102,7 @@ class IniWriter extends Zend_Config_Writer_FileAbstract $this->_config = $this->normalizeKeys($this->_config); $newconfig = $this->_config; - $editor = new IniEditor(file_get_contents($this->_filename), $this->options); + $editor = new IniEditor($content, $this->options); $this->diffConfigs($oldconfig, $newconfig, $editor); $this->updateSectionOrder($newconfig, $editor); return $editor->getText(); From aac161d7a03e881b4166357d0b3a57591b4178bc Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 4 Nov 2014 14:48:24 +0100 Subject: [PATCH 05/36] config forms: prepend our custom view decorator when saving the configuration failed --- application/forms/ConfigForm.php | 4 +++- application/views/scripts/showConfiguration.phtml | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/application/forms/ConfigForm.php b/application/forms/ConfigForm.php index d1f2ed1dd..585bd6914 100644 --- a/application/forms/ConfigForm.php +++ b/application/forms/ConfigForm.php @@ -5,6 +5,7 @@ namespace Icinga\Form; use Exception; +use Zend_Form_Decorator_Abstract; use Icinga\Web\Form; use Icinga\Application\Config; use Icinga\File\Ini\IniWriter; @@ -58,7 +59,8 @@ class ConfigForm extends Form 'viewScript' => 'showConfiguration.phtml', 'errorMessage' => $e->getMessage(), 'configString' => $writer->render(), - 'filePath' => $this->config->getConfigFile() + 'filePath' => $this->config->getConfigFile(), + 'placement' => Zend_Form_Decorator_Abstract::PREPEND )); return false; } diff --git a/application/views/scripts/showConfiguration.phtml b/application/views/scripts/showConfiguration.phtml index 1dde3b16b..682b349c9 100644 --- a/application/views/scripts/showConfiguration.phtml +++ b/application/views/scripts/showConfiguration.phtml @@ -1,6 +1,5 @@

translate('Saving Configuration Failed'); ?>

-

translate('The file %s couldn\'t be stored. (Error: "%s")'), @@ -25,4 +24,4 @@

     escape($configString); ?>
   
-

\ No newline at end of file +

From 0f48382f6912dbd39e4419773b2a71591d34ae1e Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 4 Nov 2014 16:14:39 +0100 Subject: [PATCH 06/36] security: Add form for granting and revoking user and group permissions refs #5647 --- application/forms/Security/PermissionForm.php | 216 ++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 application/forms/Security/PermissionForm.php diff --git a/application/forms/Security/PermissionForm.php b/application/forms/Security/PermissionForm.php new file mode 100644 index 000000000..87dd8a318 --- /dev/null +++ b/application/forms/Security/PermissionForm.php @@ -0,0 +1,216 @@ +getModuleManager()->getLoadedModules() as $module) { + foreach ($module->getProvidedPermissions() as $permission) { + /** @var object $permission */ + $this->providedPermissions[$permission->name] = $permission->name . ': ' . $permission->description; + } + } + $this->setSubmitLabel(t('Grant Permissions')); + } + + /** + * (non-PHPDoc) + * @see \Icinga\Web\Form::createElements() For the method documentation. + */ + public function createElements(array $formData = array()) + { + $this->addElements(array( + array( + 'text', + 'name', + array( + 'required' => true, + 'label' => t('Permission Name'), + 'description' => t('The name of the permission') + ), + ), + array( + 'textarea', + 'users', + array( + 'label' => t('Users'), + 'description' => t('Comma-separated list of users that are granted the permissions') + ), + ), + array( + 'textarea', + 'groups', + array( + 'label' => t('Groups'), + 'description' => t('Comma-separated list of groups that are granted the permissions') + ), + ), + array( + 'multiselect', + 'permissions', + array( + 'label' => t('Permissions Set'), + 'description' => t('The permissions to grant. You may select more than one permission'), + 'multiOptions' => $this->providedPermissions + ) + ) + )); + return $this; + } + + /** + * Load a permission + * + * @param string $name The name of the permission + * + * @return $this + * + * @throws LogicException If the config is not set + * @see ConfigForm::setConfig() For setting the config. + */ + public function load($name) + { + if (! isset($this->config)) { + throw new LogicException(sprintf('Can\'t load permission \'%s\'. Config is not set', $name)); + } + if (! isset($this->config->{$name})) { + throw new InvalidArgumentException(sprintf( + t('Can\'t load permission \'%s\'. Permission does not exist'), + $name + )); + } + $permission = $this->config->{$name}->toArray(); + $permission['permissions'] = ! empty($permission['permissions']) + ? String::trimSplit($permission['permissions']) + : null; + $permission['name'] = $name; + $this->populate($permission); + return $this; + } + + /** + * Add a permission + * + * @param string $name The name of the permission + * @param array $values + * + * @return $this + * + * @throws LogicException If the config is not set + * @throws InvalidArgumentException If the permission to add already exists + * @see ConfigForm::setConfig() For setting the config. + */ + public function add($name, array $values) + { + if (! isset($this->config)) { + throw new LogicException(sprintf('Can\'t add permission \'%s\'. Config is not set', $name)); + } + if (isset($this->config->{$name})) { + throw new InvalidArgumentException(sprintf( + t('Can\'t add permission \'%s\'. Permission already exists'), + $name + )); + } + $this->config->{$name} = $values; + return $this; + } + + + /** + * Update a permission + * + * @param string $name The possibly new name of the permission + * @param array $values + * @param string $oldName The name of the permission to update + * + * @return $this + * + * @throws LogicException If the config is not set + * @throws InvalidArgumentException If the permission to update does not exist + * @see ConfigForm::setConfig() For setting the config. + */ + public function update($name, array $values, $oldName) + { + if (! isset($this->config)) { + throw new LogicException(sprintf('Can\'t update permission \'%s\'. Config is not set', $name)); + } + if ($name !== $oldName) { + // The permission got a new name + $this->remove($oldName); + $this->add($name, $values); + } else { + if (! isset($this->config->{$name})) { + throw new InvalidArgumentException(sprintf( + t('Can\'t update permission \'%s\'. Permission does not exist'), + $name + )); + } + $this->config->{$name} = $values; + } + return $this; + } + + /** + * Remove a permission + * + * @param string $name The name of the permission + * + * @return $this + * + * @throws LogicException If the config is not set + * @throws InvalidArgumentException If the permission does not exist + * @see ConfigForm::setConfig() For setting the config. + */ + public function remove($name) + { + if (! isset($this->config)) { + throw new LogicException(sprintf('Can\'t remove permission \'%s\'. Config is not set', $name)); + } + if (! isset($this->config->{$name})) { + throw new InvalidArgumentException(sprintf( + t('Can\'t remove permission \'%s\'. Permission does not exist'), + $name + )); + } + unset($this->config->{$name}); + return $this; + } + + /** + * (non-PHPDoc) + * @see \Zend_Form::getValues() For the method documentation. + */ + public function getValues($suppressArrayNotation = false) + { + $permissions = $this->getElement('permissions')->getValue(); + return array( + 'users' => $this->getElement('users')->getValue(), + 'groups' => $this->getElement('groups')->getValue(), + 'permissions' => ! empty($permissions) ? implode(', ', $permissions) : null + ); + } +} From d2eddcbec6bff6ff640e5c76de302382ca689927 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 4 Nov 2014 16:15:06 +0100 Subject: [PATCH 07/36] Introduce Form::setOnSuccess() in favor of overriding the constructor Zend_Form uses setters for options if a respective setter method exists. It is not necessary to override the constructor for introducing new options. --- library/Icinga/Web/Form.php | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php index 82f4501a1..8eab0f6a5 100644 --- a/library/Icinga/Web/Form.php +++ b/library/Icinga/Web/Form.php @@ -108,30 +108,23 @@ class Form extends Zend_Form ); /** - * Create a new form + * Set a callback that is called instead of this form's onSuccess method * - * Accepts an additional option `onSuccess' which is a callback that is called instead of this - * form's method. It is called using the following signature: (Request $request, Form $form). + * It is called using the following signature: (Request $request, Form $form). * - * @see Zend_Form::__construct() + * @param callable $onSuccess Callback * - * @throws LogicException In case `onSuccess' is not callable + * @return $this + * + * @throws LogicException If the callback is not callable */ - public function __construct($options = null) + public function setOnSuccess($onSuccess) { - if (is_array($options) && isset($options['onSuccess'])) { - $this->onSuccess = $options['onSuccess']; - unset($options['onSuccess']); - } elseif (isset($options->onSuccess)) { - $this->onSuccess = $options->onSuccess; - unset($options->onSuccess); - } - - if ($this->onSuccess !== null && false === is_callable($this->onSuccess)) { + if (! is_callable($onSuccess)) { throw new LogicException('The option `onSuccess\' is not callable'); } - - parent::__construct($options); + $this->onSuccess = $onSuccess; + return $this; } /** From d0fc38ce94980877f68e490dbb4a847f40f5ce92 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 4 Nov 2014 16:17:54 +0100 Subject: [PATCH 08/36] security: Add controller for creating, updating and removing permissions refs #5647 --- .../controllers/SecurityController.php | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 application/controllers/SecurityController.php diff --git a/application/controllers/SecurityController.php b/application/controllers/SecurityController.php new file mode 100644 index 000000000..c3f9dc60d --- /dev/null +++ b/application/controllers/SecurityController.php @@ -0,0 +1,130 @@ +view->permissions = Config::app('permissions', true); + $this->view->restrictions = Config::app('restrictions', true); + } + + public function newPermissionAction() + { + $permission = new PermissionForm(array( + 'onSuccess' => function (Request $request, PermissionForm $permission) { + $name = $permission->getElement('name')->getValue(); + $values = $permission->getValues(); + try { + $permission->add($name, $values); + } catch (InvalidArgumentException $e) { + $permission->addError($e->getMessage()); + return false; + } + if ($permission->save()) { + Notification::success(t('Permissions granted')); + return true; + } + return false; + } + )); + $permission + ->setIniConfig(Config::app('permissions', true)) + ->setRedirectUrl('security') + ->handleRequest(); + $this->view->form = $permission; + } + + public function updatePermissionAction() + { + $name = $this->_request->getParam('permission'); + if (empty($name)) { + throw new Zend_Controller_Action_Exception( + sprintf($this->translate('Required parameter \'%s\' missing'), 'permission'), + 400 + ); + } + $permission = new PermissionForm(); + try { + $permission + ->setIniConfig(Config::app('permissions', true)) + ->load($name); + } catch (InvalidArgumentException $e) { + throw new Zend_Controller_Action_Exception( + $e->getMessage(), + 400 + ); + } + $permission + ->setOnSuccess(function (Request $request, PermissionForm $permission) use ($name) { + $oldName = $name; + $name = $permission->getElement('name')->getValue(); + $values = $permission->getValues(); + try { + $permission->update($name, $values, $oldName); + } catch (InvalidArgumentException $e) { + $permission->addError($e->getMessage()); + return false; + } + if ($permission->save()) { + Notification::success(t('Permissions granted')); + return true; + } + return false; + }) + ->setRedirectUrl('security') + ->handleRequest(); + $this->view->name = $name; + $this->view->form = $permission; + } + + public function removePermissionAction() + { + $name = $this->_request->getParam('permission'); + if (empty($name)) { + throw new Zend_Controller_Action_Exception( + sprintf($this->translate('Required parameter \'%s\' missing'), 'permission'), + 400 + ); + } + $permission = new PermissionForm(); + try { + $permission + ->setIniConfig(Config::app('permissions', true)) + ->load($name); + } catch (InvalidArgumentException $e) { + throw new Zend_Controller_Action_Exception( + $e->getMessage(), + 400 + ); + } + $confirmation = new ConfirmRemovalForm(array( + 'onSuccess' => function (Request $request, ConfirmRemovalForm $confirmation) use ($name, $permission) { + try { + $permission->remove($name); + } catch (InvalidArgumentException $e) { + Notification::error($e->getMessage()); + return false; + } + if ($permission->save()) { + Notification::success(sprintf(t('Permission \'%s\' has been successfully removed'), $name)); + return true; + } + return false; + } + )); + $confirmation + ->setRedirectUrl('security') + ->handleRequest(); + $this->view->name = $name; + $this->view->form = $confirmation; + } +} From acded327e3a85376b8cc6d09b6bb4c49cc22230e Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 4 Nov 2014 16:18:59 +0100 Subject: [PATCH 09/36] security: Add view scripts for creating, updating and removing permissions refs #5647 --- .../views/scripts/security/index.phtml | 42 +++++++++++++++++++ .../scripts/security/new-permission.phtml | 4 ++ .../scripts/security/remove-permission.phtml | 4 ++ .../scripts/security/update-permission.phtml | 4 ++ 4 files changed, 54 insertions(+) create mode 100644 application/views/scripts/security/index.phtml create mode 100644 application/views/scripts/security/new-permission.phtml create mode 100644 application/views/scripts/security/remove-permission.phtml create mode 100644 application/views/scripts/security/update-permission.phtml diff --git a/application/views/scripts/security/index.phtml b/application/views/scripts/security/index.phtml new file mode 100644 index 000000000..6a4e17fda --- /dev/null +++ b/application/views/scripts/security/index.phtml @@ -0,0 +1,42 @@ +
+
+

translate('Permissions') ?>

+ isEmpty()): ?> + translate('No permissions found.') ?> + + + + + + + + + + + + $permission): /** @var object $permission */ ?> + + + + + + + + + +
translate('Name') ?>translate('Permissions') ?>translate('Users') ?>translate('Groups') ?>
+ escape($name) ?> + + escape($permission->permissions) ?>escape($permission->users) ?>escape($permission->groups) ?> + + translate('Remove permission') ?> + +
+ + + translate('Grant Permissions') ?> + +
+
diff --git a/application/views/scripts/security/new-permission.phtml b/application/views/scripts/security/new-permission.phtml new file mode 100644 index 000000000..52b3badfd --- /dev/null +++ b/application/views/scripts/security/new-permission.phtml @@ -0,0 +1,4 @@ +
+

translate('New Permission') ?>

+ +
diff --git a/application/views/scripts/security/remove-permission.phtml b/application/views/scripts/security/remove-permission.phtml new file mode 100644 index 000000000..6841681f2 --- /dev/null +++ b/application/views/scripts/security/remove-permission.phtml @@ -0,0 +1,4 @@ +
+

translate('Remove Permission %s'), $name) ?>

+ +
diff --git a/application/views/scripts/security/update-permission.phtml b/application/views/scripts/security/update-permission.phtml new file mode 100644 index 000000000..e7c45fe66 --- /dev/null +++ b/application/views/scripts/security/update-permission.phtml @@ -0,0 +1,4 @@ +
+

translate('Update Permission %s'), $name) ?>

+ +
From a06568ce417ebfd3ab2fbce80852a1d31c7c90d8 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 4 Nov 2014 16:19:20 +0100 Subject: [PATCH 10/36] security: Add menu entry for security refs #5647 --- library/Icinga/Web/Menu.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/Icinga/Web/Menu.php b/library/Icinga/Web/Menu.php index 870c2f1f3..a556484e9 100644 --- a/library/Icinga/Web/Menu.php +++ b/library/Icinga/Web/Menu.php @@ -68,7 +68,7 @@ class Menu implements RecursiveIterator * @var MenuItemRenderer */ protected $itemRenderer = null; - + /* * Parent menu * @@ -223,6 +223,10 @@ class Menu implements RecursiveIterator 'url' => 'config/modules', 'priority' => 400 )); + $section->add(t('Security'), array( + 'url' => 'security', + 'priority' => 500 + )); if (Logger::writesToFile()) { $section->add(t('Application Log'), array( @@ -691,7 +695,7 @@ class Menu implements RecursiveIterator } /** - * PHP 5.3 GC should not leak, but just to be on the safe side... + * PHP 5.3 GC should not leak, but just to be on the safe side... */ public function __destruct() { From 945d94491a5eac6961414a0ecf18aabba66b8501 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Thu, 6 Nov 2014 17:38:38 +0100 Subject: [PATCH 11/36] security: add form for setting and removing user and group restrictions refs #5647 --- .../forms/Security/RestrictionForm.php | 224 ++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 application/forms/Security/RestrictionForm.php diff --git a/application/forms/Security/RestrictionForm.php b/application/forms/Security/RestrictionForm.php new file mode 100644 index 000000000..8ace80a6c --- /dev/null +++ b/application/forms/Security/RestrictionForm.php @@ -0,0 +1,224 @@ +getModuleManager()->getLoadedModules() as $module) { + foreach ($module->getProvidedRestrictions() as $restriction) { + /** @var object $restriction */ + $this->providedRestrictions[$restriction->name] = $restriction->name . ': ' . $restriction->description; + } + } + $this->setSubmitLabel(t('Set Restriction')); + } + + /** + * (non-PHPDoc) + * @see \Icinga\Web\Form::createElements() For the method documentation. + */ + public function createElements(array $formData = array()) + { + $this->addElements(array( + array( + 'text', + 'name', + array( + 'required' => true, + 'label' => t('Name'), + 'description' => t('The name of the restriction') + ), + ), + array( + 'textarea', + 'users', + array( + 'label' => t('Users'), + 'description' => t('Comma-separated list of users who are subject to the restriction') + ), + ), + array( + 'textarea', + 'groups', + array( + 'label' => t('Groups'), + 'description' => t('Comma-separated list of groups that are subject to the restriction') + ), + ), + array( + 'select', + 'restriction_name', + array( + 'required' => true, + 'label' => t('Restriction Name'), + 'description' => t('The restriction to set'), + 'multiOptions' => $this->providedRestrictions + ) + ), + array( + 'text', + 'restriction_definition', + array( + 'required' => true, + 'label' => t('Restriction'), + 'description' => t('The restriction definition. Most likely a URL filter') + ), + ), + )); + return $this; + } + + /** + * Load a restriction + * + * @param string $name The name of the restriction + * + * @return $this + * + * @throws LogicException If the config is not set + * @see ConfigForm::setConfig() For setting the config. + */ + public function load($name) + { + if (! isset($this->config)) { + throw new LogicException(sprintf('Can\'t load restriction \'%s\'. Config is not set', $name)); + } + if (! isset($this->config->{$name})) { + throw new InvalidArgumentException(sprintf( + t('Can\'t load restriction \'%s\'. Restriction does not exist'), + $name + )); + } + $restriction = $this->config->{$name}->toArray(); + $restriction['restriction_name'] = $restriction['name']; + $restriction['name'] = $name; + $restriction['restriction_definition'] = $restriction['restriction']; + unset($restriction['restriction']); + $this->populate($restriction); + return $this; + } + + /** + * Add a restriction + * + * @param string $name The name of the restriction + * @param array $values + * + * @return $this + * + * @throws LogicException If the config is not set + * @throws InvalidArgumentException If the restriction to add already exists + * @see ConfigForm::setConfig() For setting the config. + */ + public function add($name, array $values) + { + if (! isset($this->config)) { + throw new LogicException(sprintf('Can\'t add restriction \'%s\'. Config is not set', $name)); + } + if (isset($this->config->{$name})) { + throw new InvalidArgumentException(sprintf( + t('Can\'t add restriction \'%s\'. Restriction already exists'), + $name + )); + } + $this->config->{$name} = $values; + return $this; + } + + /** + * Remove a restriction + * + * @param string $name The name of the restriction + * + * @return $this + * + * @throws LogicException If the config is not set + * @throws InvalidArgumentException If the restriction does not exist + * @see ConfigForm::setConfig() For setting the config. + */ + public function remove($name) + { + if (! isset($this->config)) { + throw new LogicException(sprintf('Can\'t remove restriction \'%s\'. Config is not set', $name)); + } + if (! isset($this->config->{$name})) { + throw new InvalidArgumentException(sprintf( + t('Can\'t remove restriction \'%s\'. Restriction does not exist'), + $name + )); + } + unset($this->config->{$name}); + return $this; + } + + /** + * Update a restriction + * + * @param string $name The possibly new name of the restriction + * @param array $values + * @param string $oldName The name of the restriction to update + * + * @return $this + * + * @throws LogicException If the config is not set + * @throws InvalidArgumentException If the restriction to update does not exist + * @see ConfigForm::setConfig() For setting the config. + */ + public function update($name, array $values, $oldName) + { + if (! isset($this->config)) { + throw new LogicException(sprintf('Can\'t update restriction \'%s\'. Config is not set', $name)); + } + if ($name !== $oldName) { + // The restriction got a new name + $this->remove($oldName); + $this->add($name, $values); + } else { + if (! isset($this->config->{$name})) { + throw new InvalidArgumentException(sprintf( + t('Can\'t update restriction \'%s\'. Restriction does not exist'), + $name + )); + } + $this->config->{$name} = $values; + } + return $this; + } + + /** + * (non-PHPDoc) + * @see \Zend_Form::getValues() For the method documentation. + */ + public function getValues($suppressArrayNotation = false) + { + return array( + 'users' => $this->getElement('users')->getValue(), + 'groups' => $this->getElement('groups')->getValue(), + 'name' => $this->getElement('restriction_name')->getValue(), + 'restriction' => $this->getElement('restriction_definition')->getValue() + ); + } +} From ebd77ee5c10145a8ebb82968c44c441a3db29f5c Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Thu, 6 Nov 2014 17:39:20 +0100 Subject: [PATCH 12/36] security: Add actions for creating, updating and removing restrictions refs #5647 --- .../controllers/SecurityController.php | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/application/controllers/SecurityController.php b/application/controllers/SecurityController.php index c3f9dc60d..bcd83a5c3 100644 --- a/application/controllers/SecurityController.php +++ b/application/controllers/SecurityController.php @@ -5,6 +5,7 @@ use Icinga\Application\Config; use Icinga\Form\ConfirmRemovalForm; use Icinga\Form\Security\PermissionForm; +use Icinga\Form\Security\RestrictionForm; use Icinga\Web\Controller\ActionController; use Icinga\Web\Notification; use Icinga\Web\Request; @@ -127,4 +128,115 @@ class SecurityController extends ActionController $this->view->name = $name; $this->view->form = $confirmation; } + + public function newRestrictionAction() + { + $restriction = new RestrictionForm(array( + 'onSuccess' => function (Request $request, RestrictionForm $restriction) { + $name = $restriction->getElement('name')->getValue(); + $values = $restriction->getValues(); + try { + $restriction->add($name, $values); + } catch (InvalidArgumentException $e) { + $restriction->addError($e->getMessage()); + return false; + } + if ($restriction->save()) { + Notification::success(t('Restriction set')); + return true; + } + return false; + } + )); + $restriction + ->setIniConfig(Config::app('restrictions', true)) + ->setRedirectUrl('security') + ->handleRequest(); + $this->view->form = $restriction; + } + + public function updateRestrictionAction() + { + $name = $this->_request->getParam('restriction'); + if (empty($name)) { + throw new Zend_Controller_Action_Exception( + sprintf($this->translate('Required parameter \'%s\' missing'), 'restriction'), + 400 + ); + } + $restriction = new RestrictionForm(); + try { + $restriction + ->setIniConfig(Config::app('restrictions', true)) + ->load($name); + } catch (InvalidArgumentException $e) { + throw new Zend_Controller_Action_Exception( + $e->getMessage(), + 400 + ); + } + $restriction + ->setOnSuccess(function (Request $request, RestrictionForm $restriction) use ($name) { + $oldName = $name; + $name = $restriction->getElement('name')->getValue(); + $values = $restriction->getValues(); + try { + $restriction->update($name, $values, $oldName); + } catch (InvalidArgumentException $e) { + $restriction->addError($e->getMessage()); + return false; + } + if ($restriction->save()) { + Notification::success(t('Restriction set')); + return true; + } + return false; + }) + ->setRedirectUrl('security') + ->handleRequest(); + $this->view->name = $name; + $this->view->form = $restriction; + } + + public function removeRestrictionAction() + { + $name = $this->_request->getParam('restriction'); + if (empty($name)) { + throw new Zend_Controller_Action_Exception( + sprintf($this->translate('Required parameter \'%s\' missing'), 'restriction'), + 400 + ); + } + $restriction = new RestrictionForm(); + try { + $restriction + ->setIniConfig(Config::app('restrictions', true)) + ->load($name); + } catch (InvalidArgumentException $e) { + throw new Zend_Controller_Action_Exception( + $e->getMessage(), + 400 + ); + } + $confirmation = new ConfirmRemovalForm(array( + 'onSuccess' => function (Request $request, ConfirmRemovalForm $confirmation) use ($name, $restriction) { + try { + $restriction->remove($name); + } catch (InvalidArgumentException $e) { + Notification::error($e->getMessage()); + return false; + } + if ($restriction->save()) { + Notification::success(sprintf(t('Restriction \'%s\' has been successfully removed'), $name)); + return true; + } + return false; + } + )); + $confirmation + ->setRedirectUrl('security') + ->handleRequest(); + $this->view->name = $name; + $this->view->form = $confirmation; + } } From 5c8af797041f126d0734bc1d01985abb272b237c Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Thu, 6 Nov 2014 17:39:51 +0100 Subject: [PATCH 13/36] security: Add view scripts for creating, updating and removing restrictions refs #5647 --- .../views/scripts/security/index.phtml | 42 +++++++++++++++++++ .../scripts/security/new-restriction.phtml | 4 ++ .../scripts/security/remove-restriction.phtml | 4 ++ .../scripts/security/update-restriction.phtml | 4 ++ 4 files changed, 54 insertions(+) create mode 100644 application/views/scripts/security/new-restriction.phtml create mode 100644 application/views/scripts/security/remove-restriction.phtml create mode 100644 application/views/scripts/security/update-restriction.phtml diff --git a/application/views/scripts/security/index.phtml b/application/views/scripts/security/index.phtml index 6a4e17fda..26ffcc7a6 100644 --- a/application/views/scripts/security/index.phtml +++ b/application/views/scripts/security/index.phtml @@ -39,4 +39,46 @@ translate('Grant Permissions') ?>
+
+

translate('Restrictions') ?>

+ isEmpty()): ?> + translate('No restrictions found.') ?> + + + + + + + + + + + + + $restriction): /** @var object $restriction */ ?> + + + + + + + + + + +
translate('Name') ?>translate('Restriction Name') ?>translate('Restriction') ?>translate('Users') ?>translate('Groups') ?>
+ escape($name) ?> + + escape($restriction->name) ?>escape($restriction->restriction) ?>escape($restriction->users) ?>escape($restriction->groups) ?> + + translate('Remove restriction') ?> + +
+ + + translate('Set Restriction') ?> + +
diff --git a/application/views/scripts/security/new-restriction.phtml b/application/views/scripts/security/new-restriction.phtml new file mode 100644 index 000000000..6fd5a6706 --- /dev/null +++ b/application/views/scripts/security/new-restriction.phtml @@ -0,0 +1,4 @@ +
+

translate('New Restriction') ?>

+ +
diff --git a/application/views/scripts/security/remove-restriction.phtml b/application/views/scripts/security/remove-restriction.phtml new file mode 100644 index 000000000..d621716cf --- /dev/null +++ b/application/views/scripts/security/remove-restriction.phtml @@ -0,0 +1,4 @@ +
+

translate('Remove Restriction %s'), $name) ?>

+ +
diff --git a/application/views/scripts/security/update-restriction.phtml b/application/views/scripts/security/update-restriction.phtml new file mode 100644 index 000000000..8766d8658 --- /dev/null +++ b/application/views/scripts/security/update-restriction.phtml @@ -0,0 +1,4 @@ +
+

translate('Update Restriction %s'), $name) ?>

+ +
From 84b98cd58d761f17afecb24400b594203c6b0f54 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 18 Nov 2014 17:10:14 +0100 Subject: [PATCH 14/36] Security: Fix Form namespace --- application/controllers/SecurityController.php | 6 +++--- application/forms/Security/PermissionForm.php | 4 ++-- application/forms/Security/RestrictionForm.php | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/application/controllers/SecurityController.php b/application/controllers/SecurityController.php index bcd83a5c3..14f856375 100644 --- a/application/controllers/SecurityController.php +++ b/application/controllers/SecurityController.php @@ -3,9 +3,9 @@ // {{{ICINGA_LICENSE_HEADER}}} use Icinga\Application\Config; -use Icinga\Form\ConfirmRemovalForm; -use Icinga\Form\Security\PermissionForm; -use Icinga\Form\Security\RestrictionForm; +use Icinga\Forms\ConfirmRemovalForm; +use Icinga\Forms\Security\PermissionForm; +use Icinga\Forms\Security\RestrictionForm; use Icinga\Web\Controller\ActionController; use Icinga\Web\Notification; use Icinga\Web\Request; diff --git a/application/forms/Security/PermissionForm.php b/application/forms/Security/PermissionForm.php index 87dd8a318..c8826a1d0 100644 --- a/application/forms/Security/PermissionForm.php +++ b/application/forms/Security/PermissionForm.php @@ -2,12 +2,12 @@ // {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}} -namespace Icinga\Form\Security; +namespace Icinga\Forms\Security; use InvalidArgumentException; use LogicException; use Icinga\Application\Icinga; -use Icinga\Form\ConfigForm; +use Icinga\Forms\ConfigForm; use Icinga\Util\String; /** diff --git a/application/forms/Security/RestrictionForm.php b/application/forms/Security/RestrictionForm.php index 8ace80a6c..f1d59bf44 100644 --- a/application/forms/Security/RestrictionForm.php +++ b/application/forms/Security/RestrictionForm.php @@ -2,12 +2,12 @@ // {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}} -namespace Icinga\Form\Security; +namespace Icinga\Forms\Security; use InvalidArgumentException; use LogicException; use Icinga\Application\Icinga; -use Icinga\Form\ConfigForm; +use Icinga\Forms\ConfigForm; /** * Form for setting and removing user and group restrictions From 8aab5dc0f03e4a5f5c5a71ebced79a34f09b618b Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 14:21:00 +0100 Subject: [PATCH 15/36] Security: Show roles instead of permissions and restrictions refs #5647 --- .../views/scripts/security/index.phtml | 66 ++++--------------- 1 file changed, 12 insertions(+), 54 deletions(-) diff --git a/application/views/scripts/security/index.phtml b/application/views/scripts/security/index.phtml index 26ffcc7a6..3dc571ce9 100644 --- a/application/views/scripts/security/index.phtml +++ b/application/views/scripts/security/index.phtml @@ -1,8 +1,8 @@
-

translate('Permissions') ?>

- isEmpty()): ?> - translate('No permissions found.') ?> +

translate('Roles') ?>

+ isEmpty()): ?> + translate('No roles found.') ?> @@ -14,20 +14,20 @@ - $permission): /** @var object $permission */ ?> + $role): /** @var object $role */ ?> - - - + + + @@ -35,50 +35,8 @@
escape($name) ?> escape($permission->permissions) ?>escape($permission->users) ?>escape($permission->groups) ?>escape($role->permissions) ?>escape($role->users) ?>escape($role->groups) ?> - - translate('Remove permission') ?> + + translate('Remove role') ?>
- - translate('Grant Permissions') ?> - -
-
-

translate('Restrictions') ?>

- isEmpty()): ?> - translate('No restrictions found.') ?> - - - - - - - - - - - - - $restriction): /** @var object $restriction */ ?> - - - - - - - - - - -
translate('Name') ?>translate('Restriction Name') ?>translate('Restriction') ?>translate('Users') ?>translate('Groups') ?>
- escape($name) ?> - - escape($restriction->name) ?>escape($restriction->restriction) ?>escape($restriction->users) ?>escape($restriction->groups) ?> - - translate('Remove restriction') ?> - -
- - - translate('Set Restriction') ?> + + translate('New Role') ?>
From 0a6440a6a69fa0cc3bc875d0207a1e2854bbf650 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 14:22:33 +0100 Subject: [PATCH 16/36] Security: Add role form This form will replace the permission and restriction form refs #5647 --- application/forms/Security/RoleForm.php | 225 ++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 application/forms/Security/RoleForm.php diff --git a/application/forms/Security/RoleForm.php b/application/forms/Security/RoleForm.php new file mode 100644 index 000000000..5861fa6fa --- /dev/null +++ b/application/forms/Security/RoleForm.php @@ -0,0 +1,225 @@ +getModuleManager()->getLoadedModules() as $module) { + foreach ($module->getProvidedPermissions() as $permission) { + /** @var object $permission */ + $this->providedPermissions[$permission->name] = $permission->name . ': ' . $permission->description; + } + foreach ($module->getProvidedRestrictions() as $restriction) { + /** @var object $restriction */ + $this->providedRestrictions[$restriction->name] = $restriction->name . ': ' . $restriction->description; + } + } + } + + /** + * (non-PHPDoc) + * @see \Icinga\Web\Form::createElements() For the method documentation. + */ + public function createElements(array $formData = array()) + { + $this->addElements(array( + array( + 'text', + 'name', + array( + 'required' => true, + 'label' => t('Role Name'), + 'description' => t('The name of the role') + ), + ), + array( + 'textarea', + 'users', + array( + 'label' => t('Users'), + 'description' => t('Comma-separated list of users that are assigned to the role') + ), + ), + array( + 'textarea', + 'groups', + array( + 'label' => t('Groups'), + 'description' => t('Comma-separated list of groups that are assigned to the role') + ), + ), + array( + 'multiselect', + 'permissions', + array( + 'label' => t('Permissions Set'), + 'description' => t('The permissions to grant. You may select more than one permission'), + 'multiOptions' => $this->providedPermissions + ) + ) + )); + return $this; + } + + /** + * Load a role + * + * @param string $name The name of the role + * + * @return $this + * + * @throws LogicException If the config is not set + * @see ConfigForm::setConfig() For setting the config. + */ + public function load($name) + { + if (! isset($this->config)) { + throw new LogicException(sprintf('Can\'t load role \'%s\'. Config is not set', $name)); + } + if (! $this->config->hasSection($name)) { + throw new InvalidArgumentException(sprintf( + t('Can\'t load role \'%s\'. Role does not exist'), + $name + )); + } + $role = $this->config->{$name}->toArray(); + $role['permissions'] = ! empty($role['permissions']) + ? String::trimSplit($role['permissions']) + : null; + $role['name'] = $name; + $this->populate($role); + return $this; + } + + /** + * Add a role + * + * @param string $name The name of the role + * @param array $values + * + * @return $this + * + * @throws LogicException If the config is not set + * @throws InvalidArgumentException If the role to add already exists + * @see ConfigForm::setConfig() For setting the config. + */ + public function add($name, array $values) + { + if (! isset($this->config)) { + throw new LogicException(sprintf('Can\'t add role \'%s\'. Config is not set', $name)); + } + if ($this->config->hasSection($name)) { + throw new InvalidArgumentException(sprintf( + t('Can\'t add role \'%s\'. Role already exists'), + $name + )); + } + $this->config->setSection($name, $values); + return $this; + } + + /** + * Remove a role + * + * @param string $name The name of the role + * + * @return $this + * + * @throws LogicException If the config is not set + * @throws InvalidArgumentException If the role does not exist + * @see ConfigForm::setConfig() For setting the config. + */ + public function remove($name) + { + if (! isset($this->config)) { + throw new LogicException(sprintf('Can\'t remove role \'%s\'. Config is not set', $name)); + } + if (! $this->config->hasSection($name)) { + throw new InvalidArgumentException(sprintf( + t('Can\'t remove role \'%s\'. Role does not exist'), + $name + )); + } + $this->config->removeSection($name); + return $this; + } + + /** + * Update a role + * + * @param string $name The possibly new name of the role + * @param array $values + * @param string $oldName The name of the role to update + * + * @return $this + * + * @throws LogicException If the config is not set + * @throws InvalidArgumentException If the role to update does not exist + * @see ConfigForm::setConfig() For setting the config. + */ + public function update($name, array $values, $oldName) + { + if (! isset($this->config)) { + throw new LogicException(sprintf('Can\'t update role \'%s\'. Config is not set', $name)); + } + if ($name !== $oldName) { + // The permission got a new name + $this->remove($oldName); + $this->add($name, $values); + } else { + if (! $this->config->hasSection($name)) { + throw new InvalidArgumentException(sprintf( + t('Can\'t update role \'%s\'. Role does not exist'), + $name + )); + } + $this->config->setSection($name, $values); + } + return $this; + } + + /** + * (non-PHPDoc) + * @see \Zend_Form::getValues() For the method documentation. + */ + public function getValues($suppressArrayNotation = false) + { + $permissions = $this->getElement('permissions')->getValue(); + return array( + 'users' => $this->getElement('users')->getValue(), + 'groups' => $this->getElement('groups')->getValue(), + 'permissions' => ! empty($permissions) ? implode(', ', $permissions) : null + ); + } +} From 7592642991233222222215361f398e126ca5d7d7 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 14:23:07 +0100 Subject: [PATCH 17/36] Security: Remove the permission form refs #5647 --- application/forms/Security/PermissionForm.php | 216 ------------------ 1 file changed, 216 deletions(-) delete mode 100644 application/forms/Security/PermissionForm.php diff --git a/application/forms/Security/PermissionForm.php b/application/forms/Security/PermissionForm.php deleted file mode 100644 index c8826a1d0..000000000 --- a/application/forms/Security/PermissionForm.php +++ /dev/null @@ -1,216 +0,0 @@ -getModuleManager()->getLoadedModules() as $module) { - foreach ($module->getProvidedPermissions() as $permission) { - /** @var object $permission */ - $this->providedPermissions[$permission->name] = $permission->name . ': ' . $permission->description; - } - } - $this->setSubmitLabel(t('Grant Permissions')); - } - - /** - * (non-PHPDoc) - * @see \Icinga\Web\Form::createElements() For the method documentation. - */ - public function createElements(array $formData = array()) - { - $this->addElements(array( - array( - 'text', - 'name', - array( - 'required' => true, - 'label' => t('Permission Name'), - 'description' => t('The name of the permission') - ), - ), - array( - 'textarea', - 'users', - array( - 'label' => t('Users'), - 'description' => t('Comma-separated list of users that are granted the permissions') - ), - ), - array( - 'textarea', - 'groups', - array( - 'label' => t('Groups'), - 'description' => t('Comma-separated list of groups that are granted the permissions') - ), - ), - array( - 'multiselect', - 'permissions', - array( - 'label' => t('Permissions Set'), - 'description' => t('The permissions to grant. You may select more than one permission'), - 'multiOptions' => $this->providedPermissions - ) - ) - )); - return $this; - } - - /** - * Load a permission - * - * @param string $name The name of the permission - * - * @return $this - * - * @throws LogicException If the config is not set - * @see ConfigForm::setConfig() For setting the config. - */ - public function load($name) - { - if (! isset($this->config)) { - throw new LogicException(sprintf('Can\'t load permission \'%s\'. Config is not set', $name)); - } - if (! isset($this->config->{$name})) { - throw new InvalidArgumentException(sprintf( - t('Can\'t load permission \'%s\'. Permission does not exist'), - $name - )); - } - $permission = $this->config->{$name}->toArray(); - $permission['permissions'] = ! empty($permission['permissions']) - ? String::trimSplit($permission['permissions']) - : null; - $permission['name'] = $name; - $this->populate($permission); - return $this; - } - - /** - * Add a permission - * - * @param string $name The name of the permission - * @param array $values - * - * @return $this - * - * @throws LogicException If the config is not set - * @throws InvalidArgumentException If the permission to add already exists - * @see ConfigForm::setConfig() For setting the config. - */ - public function add($name, array $values) - { - if (! isset($this->config)) { - throw new LogicException(sprintf('Can\'t add permission \'%s\'. Config is not set', $name)); - } - if (isset($this->config->{$name})) { - throw new InvalidArgumentException(sprintf( - t('Can\'t add permission \'%s\'. Permission already exists'), - $name - )); - } - $this->config->{$name} = $values; - return $this; - } - - - /** - * Update a permission - * - * @param string $name The possibly new name of the permission - * @param array $values - * @param string $oldName The name of the permission to update - * - * @return $this - * - * @throws LogicException If the config is not set - * @throws InvalidArgumentException If the permission to update does not exist - * @see ConfigForm::setConfig() For setting the config. - */ - public function update($name, array $values, $oldName) - { - if (! isset($this->config)) { - throw new LogicException(sprintf('Can\'t update permission \'%s\'. Config is not set', $name)); - } - if ($name !== $oldName) { - // The permission got a new name - $this->remove($oldName); - $this->add($name, $values); - } else { - if (! isset($this->config->{$name})) { - throw new InvalidArgumentException(sprintf( - t('Can\'t update permission \'%s\'. Permission does not exist'), - $name - )); - } - $this->config->{$name} = $values; - } - return $this; - } - - /** - * Remove a permission - * - * @param string $name The name of the permission - * - * @return $this - * - * @throws LogicException If the config is not set - * @throws InvalidArgumentException If the permission does not exist - * @see ConfigForm::setConfig() For setting the config. - */ - public function remove($name) - { - if (! isset($this->config)) { - throw new LogicException(sprintf('Can\'t remove permission \'%s\'. Config is not set', $name)); - } - if (! isset($this->config->{$name})) { - throw new InvalidArgumentException(sprintf( - t('Can\'t remove permission \'%s\'. Permission does not exist'), - $name - )); - } - unset($this->config->{$name}); - return $this; - } - - /** - * (non-PHPDoc) - * @see \Zend_Form::getValues() For the method documentation. - */ - public function getValues($suppressArrayNotation = false) - { - $permissions = $this->getElement('permissions')->getValue(); - return array( - 'users' => $this->getElement('users')->getValue(), - 'groups' => $this->getElement('groups')->getValue(), - 'permissions' => ! empty($permissions) ? implode(', ', $permissions) : null - ); - } -} From f556fc43e917f998554c5d4a42e1fbe74970d68f Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 14:24:20 +0100 Subject: [PATCH 18/36] Security: Remove the restriction form refs #5647 --- .../forms/Security/RestrictionForm.php | 224 ------------------ 1 file changed, 224 deletions(-) delete mode 100644 application/forms/Security/RestrictionForm.php diff --git a/application/forms/Security/RestrictionForm.php b/application/forms/Security/RestrictionForm.php deleted file mode 100644 index f1d59bf44..000000000 --- a/application/forms/Security/RestrictionForm.php +++ /dev/null @@ -1,224 +0,0 @@ -getModuleManager()->getLoadedModules() as $module) { - foreach ($module->getProvidedRestrictions() as $restriction) { - /** @var object $restriction */ - $this->providedRestrictions[$restriction->name] = $restriction->name . ': ' . $restriction->description; - } - } - $this->setSubmitLabel(t('Set Restriction')); - } - - /** - * (non-PHPDoc) - * @see \Icinga\Web\Form::createElements() For the method documentation. - */ - public function createElements(array $formData = array()) - { - $this->addElements(array( - array( - 'text', - 'name', - array( - 'required' => true, - 'label' => t('Name'), - 'description' => t('The name of the restriction') - ), - ), - array( - 'textarea', - 'users', - array( - 'label' => t('Users'), - 'description' => t('Comma-separated list of users who are subject to the restriction') - ), - ), - array( - 'textarea', - 'groups', - array( - 'label' => t('Groups'), - 'description' => t('Comma-separated list of groups that are subject to the restriction') - ), - ), - array( - 'select', - 'restriction_name', - array( - 'required' => true, - 'label' => t('Restriction Name'), - 'description' => t('The restriction to set'), - 'multiOptions' => $this->providedRestrictions - ) - ), - array( - 'text', - 'restriction_definition', - array( - 'required' => true, - 'label' => t('Restriction'), - 'description' => t('The restriction definition. Most likely a URL filter') - ), - ), - )); - return $this; - } - - /** - * Load a restriction - * - * @param string $name The name of the restriction - * - * @return $this - * - * @throws LogicException If the config is not set - * @see ConfigForm::setConfig() For setting the config. - */ - public function load($name) - { - if (! isset($this->config)) { - throw new LogicException(sprintf('Can\'t load restriction \'%s\'. Config is not set', $name)); - } - if (! isset($this->config->{$name})) { - throw new InvalidArgumentException(sprintf( - t('Can\'t load restriction \'%s\'. Restriction does not exist'), - $name - )); - } - $restriction = $this->config->{$name}->toArray(); - $restriction['restriction_name'] = $restriction['name']; - $restriction['name'] = $name; - $restriction['restriction_definition'] = $restriction['restriction']; - unset($restriction['restriction']); - $this->populate($restriction); - return $this; - } - - /** - * Add a restriction - * - * @param string $name The name of the restriction - * @param array $values - * - * @return $this - * - * @throws LogicException If the config is not set - * @throws InvalidArgumentException If the restriction to add already exists - * @see ConfigForm::setConfig() For setting the config. - */ - public function add($name, array $values) - { - if (! isset($this->config)) { - throw new LogicException(sprintf('Can\'t add restriction \'%s\'. Config is not set', $name)); - } - if (isset($this->config->{$name})) { - throw new InvalidArgumentException(sprintf( - t('Can\'t add restriction \'%s\'. Restriction already exists'), - $name - )); - } - $this->config->{$name} = $values; - return $this; - } - - /** - * Remove a restriction - * - * @param string $name The name of the restriction - * - * @return $this - * - * @throws LogicException If the config is not set - * @throws InvalidArgumentException If the restriction does not exist - * @see ConfigForm::setConfig() For setting the config. - */ - public function remove($name) - { - if (! isset($this->config)) { - throw new LogicException(sprintf('Can\'t remove restriction \'%s\'. Config is not set', $name)); - } - if (! isset($this->config->{$name})) { - throw new InvalidArgumentException(sprintf( - t('Can\'t remove restriction \'%s\'. Restriction does not exist'), - $name - )); - } - unset($this->config->{$name}); - return $this; - } - - /** - * Update a restriction - * - * @param string $name The possibly new name of the restriction - * @param array $values - * @param string $oldName The name of the restriction to update - * - * @return $this - * - * @throws LogicException If the config is not set - * @throws InvalidArgumentException If the restriction to update does not exist - * @see ConfigForm::setConfig() For setting the config. - */ - public function update($name, array $values, $oldName) - { - if (! isset($this->config)) { - throw new LogicException(sprintf('Can\'t update restriction \'%s\'. Config is not set', $name)); - } - if ($name !== $oldName) { - // The restriction got a new name - $this->remove($oldName); - $this->add($name, $values); - } else { - if (! isset($this->config->{$name})) { - throw new InvalidArgumentException(sprintf( - t('Can\'t update restriction \'%s\'. Restriction does not exist'), - $name - )); - } - $this->config->{$name} = $values; - } - return $this; - } - - /** - * (non-PHPDoc) - * @see \Zend_Form::getValues() For the method documentation. - */ - public function getValues($suppressArrayNotation = false) - { - return array( - 'users' => $this->getElement('users')->getValue(), - 'groups' => $this->getElement('groups')->getValue(), - 'name' => $this->getElement('restriction_name')->getValue(), - 'restriction' => $this->getElement('restriction_definition')->getValue() - ); - } -} From 7fcfc0146491064b3d993052a011bd5bd35c94c7 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 14:26:21 +0100 Subject: [PATCH 19/36] Security: Add action for creating a new role refs #5647 --- .../controllers/SecurityController.php | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/application/controllers/SecurityController.php b/application/controllers/SecurityController.php index 14f856375..1695621b0 100644 --- a/application/controllers/SecurityController.php +++ b/application/controllers/SecurityController.php @@ -6,6 +6,7 @@ use Icinga\Application\Config; use Icinga\Forms\ConfirmRemovalForm; use Icinga\Forms\Security\PermissionForm; use Icinga\Forms\Security\RestrictionForm; +use Icinga\Forms\Security\RoleForm; use Icinga\Web\Controller\ActionController; use Icinga\Web\Notification; use Icinga\Web\Request; @@ -14,8 +15,34 @@ class SecurityController extends ActionController { public function indexAction() { - $this->view->permissions = Config::app('permissions', true); - $this->view->restrictions = Config::app('restrictions', true); + $this->view->roles = Config::app('roles', true); + } + + public function newRoleAction() + { + $role = new RoleForm(array( + 'onSuccess' => function (RoleForm $role) { + $name = $role->getElement('name')->getValue(); + $values = $role->getValues(); + try { + $role->add($name, $values); + } catch (InvalidArgumentException $e) { + $role->addError($e->getMessage()); + return false; + } + if ($role->save()) { + Notification::success(t('Role created')); + return true; + } + return false; + } + )); + $role + ->setSubmitLabel($this->translate('Create Role')) + ->setIniConfig(Config::app('roles', true)) + ->setRedirectUrl('security') + ->handleRequest(); + $this->view->form = $role; } public function newPermissionAction() From a4744fa550c353e34632791da7befb96f3d44c84 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 14:36:36 +0100 Subject: [PATCH 20/36] Security: Add action for updating roles refs #5647 --- .../controllers/SecurityController.php | 57 ++++++------------- 1 file changed, 16 insertions(+), 41 deletions(-) diff --git a/application/controllers/SecurityController.php b/application/controllers/SecurityController.php index 1695621b0..362442ded 100644 --- a/application/controllers/SecurityController.php +++ b/application/controllers/SecurityController.php @@ -45,45 +45,20 @@ class SecurityController extends ActionController $this->view->form = $role; } - public function newPermissionAction() + public function updateRoleAction() { - $permission = new PermissionForm(array( - 'onSuccess' => function (Request $request, PermissionForm $permission) { - $name = $permission->getElement('name')->getValue(); - $values = $permission->getValues(); - try { - $permission->add($name, $values); - } catch (InvalidArgumentException $e) { - $permission->addError($e->getMessage()); - return false; - } - if ($permission->save()) { - Notification::success(t('Permissions granted')); - return true; - } - return false; - } - )); - $permission - ->setIniConfig(Config::app('permissions', true)) - ->setRedirectUrl('security') - ->handleRequest(); - $this->view->form = $permission; - } - - public function updatePermissionAction() - { - $name = $this->_request->getParam('permission'); + $name = $this->_request->getParam('role'); if (empty($name)) { throw new Zend_Controller_Action_Exception( - sprintf($this->translate('Required parameter \'%s\' missing'), 'permission'), + sprintf($this->translate('Required parameter \'%s\' missing'), 'role'), 400 ); } - $permission = new PermissionForm(); + $role = new RoleForm(); + $role->setSubmitLabel($this->translate('Update Role')); try { - $permission - ->setIniConfig(Config::app('permissions', true)) + $role + ->setIniConfig(Config::app('roles', true)) ->load($name); } catch (InvalidArgumentException $e) { throw new Zend_Controller_Action_Exception( @@ -91,19 +66,19 @@ class SecurityController extends ActionController 400 ); } - $permission - ->setOnSuccess(function (Request $request, PermissionForm $permission) use ($name) { + $role + ->setOnSuccess(function (RoleForm $role) use ($name) { $oldName = $name; - $name = $permission->getElement('name')->getValue(); - $values = $permission->getValues(); + $name = $role->getElement('name')->getValue(); + $values = $role->getValues(); try { - $permission->update($name, $values, $oldName); + $role->update($name, $values, $oldName); } catch (InvalidArgumentException $e) { - $permission->addError($e->getMessage()); + $role->addError($e->getMessage()); return false; } - if ($permission->save()) { - Notification::success(t('Permissions granted')); + if ($role->save()) { + Notification::success(t('Role updated')); return true; } return false; @@ -111,7 +86,7 @@ class SecurityController extends ActionController ->setRedirectUrl('security') ->handleRequest(); $this->view->name = $name; - $this->view->form = $permission; + $this->view->form = $role; } public function removePermissionAction() From 3b680c78855d67e8ab9e1ac4e880ce70f0121b55 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 14:36:53 +0100 Subject: [PATCH 21/36] Security: Add view script for updating roles refs #5647 --- application/views/scripts/security/update-role.phtml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 application/views/scripts/security/update-role.phtml diff --git a/application/views/scripts/security/update-role.phtml b/application/views/scripts/security/update-role.phtml new file mode 100644 index 000000000..8cb235a59 --- /dev/null +++ b/application/views/scripts/security/update-role.phtml @@ -0,0 +1,4 @@ +
+

translate('Update Role %s'), $name) ?>

+ +
From 1d34d88a013a7db19d28628ff22a3b0e691902e5 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 14:37:10 +0100 Subject: [PATCH 22/36] Security: Add view script for creating roles refs #5647 --- application/views/scripts/security/new-role.phtml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 application/views/scripts/security/new-role.phtml diff --git a/application/views/scripts/security/new-role.phtml b/application/views/scripts/security/new-role.phtml new file mode 100644 index 000000000..d5f9e7e33 --- /dev/null +++ b/application/views/scripts/security/new-role.phtml @@ -0,0 +1,4 @@ +
+

translate('New Role') ?>

+ +
From f7076816eb14bfa46a69a9462b9abf732e3ae9c3 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 14:40:49 +0100 Subject: [PATCH 23/36] Security: Add action for removing roles refs #5647 --- .../controllers/SecurityController.php | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/application/controllers/SecurityController.php b/application/controllers/SecurityController.php index 362442ded..57f228500 100644 --- a/application/controllers/SecurityController.php +++ b/application/controllers/SecurityController.php @@ -89,19 +89,19 @@ class SecurityController extends ActionController $this->view->form = $role; } - public function removePermissionAction() + public function removeRoleAction() { - $name = $this->_request->getParam('permission'); + $name = $this->_request->getParam('role'); if (empty($name)) { throw new Zend_Controller_Action_Exception( - sprintf($this->translate('Required parameter \'%s\' missing'), 'permission'), + sprintf($this->translate('Required parameter \'%s\' missing'), 'role'), 400 ); } - $permission = new PermissionForm(); + $role = new RoleForm(); try { - $permission - ->setIniConfig(Config::app('permissions', true)) + $role + ->setIniConfig(Config::app('roles', true)) ->load($name); } catch (InvalidArgumentException $e) { throw new Zend_Controller_Action_Exception( @@ -110,21 +110,22 @@ class SecurityController extends ActionController ); } $confirmation = new ConfirmRemovalForm(array( - 'onSuccess' => function (Request $request, ConfirmRemovalForm $confirmation) use ($name, $permission) { + 'onSuccess' => function (ConfirmRemovalForm $confirmation) use ($name, $role) { try { - $permission->remove($name); + $role->remove($name); } catch (InvalidArgumentException $e) { Notification::error($e->getMessage()); return false; } - if ($permission->save()) { - Notification::success(sprintf(t('Permission \'%s\' has been successfully removed'), $name)); + if ($role->save()) { + Notification::success(t('Role removed')); return true; } return false; } )); $confirmation + ->setSubmitLabel($this->translate('Remove Role')) ->setRedirectUrl('security') ->handleRequest(); $this->view->name = $name; From 2c5ff341d5b2c32b9f853b9d37330225d6a369ce Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 14:41:05 +0100 Subject: [PATCH 24/36] Security: Add view script for removing roles refs #5647 --- application/views/scripts/security/remove-role.phtml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 application/views/scripts/security/remove-role.phtml diff --git a/application/views/scripts/security/remove-role.phtml b/application/views/scripts/security/remove-role.phtml new file mode 100644 index 000000000..a9360e78f --- /dev/null +++ b/application/views/scripts/security/remove-role.phtml @@ -0,0 +1,4 @@ +
+

translate('Remove Role %s'), $name) ?>

+ +
From bd400855e817b564064ab66d569e2e37ea91193d Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 14:42:04 +0100 Subject: [PATCH 25/36] Security: Remove view scripts for creating, updating and removing roles and permissions Thos are supersed by role management. refs #5647 --- application/views/scripts/security/new-permission.phtml | 4 ---- application/views/scripts/security/new-restriction.phtml | 4 ---- application/views/scripts/security/remove-permission.phtml | 4 ---- application/views/scripts/security/remove-restriction.phtml | 4 ---- application/views/scripts/security/update-permission.phtml | 4 ---- application/views/scripts/security/update-restriction.phtml | 4 ---- 6 files changed, 24 deletions(-) delete mode 100644 application/views/scripts/security/new-permission.phtml delete mode 100644 application/views/scripts/security/new-restriction.phtml delete mode 100644 application/views/scripts/security/remove-permission.phtml delete mode 100644 application/views/scripts/security/remove-restriction.phtml delete mode 100644 application/views/scripts/security/update-permission.phtml delete mode 100644 application/views/scripts/security/update-restriction.phtml diff --git a/application/views/scripts/security/new-permission.phtml b/application/views/scripts/security/new-permission.phtml deleted file mode 100644 index 52b3badfd..000000000 --- a/application/views/scripts/security/new-permission.phtml +++ /dev/null @@ -1,4 +0,0 @@ -
-

translate('New Permission') ?>

- -
diff --git a/application/views/scripts/security/new-restriction.phtml b/application/views/scripts/security/new-restriction.phtml deleted file mode 100644 index 6fd5a6706..000000000 --- a/application/views/scripts/security/new-restriction.phtml +++ /dev/null @@ -1,4 +0,0 @@ -
-

translate('New Restriction') ?>

- -
diff --git a/application/views/scripts/security/remove-permission.phtml b/application/views/scripts/security/remove-permission.phtml deleted file mode 100644 index 6841681f2..000000000 --- a/application/views/scripts/security/remove-permission.phtml +++ /dev/null @@ -1,4 +0,0 @@ -
-

translate('Remove Permission %s'), $name) ?>

- -
diff --git a/application/views/scripts/security/remove-restriction.phtml b/application/views/scripts/security/remove-restriction.phtml deleted file mode 100644 index d621716cf..000000000 --- a/application/views/scripts/security/remove-restriction.phtml +++ /dev/null @@ -1,4 +0,0 @@ -
-

translate('Remove Restriction %s'), $name) ?>

- -
diff --git a/application/views/scripts/security/update-permission.phtml b/application/views/scripts/security/update-permission.phtml deleted file mode 100644 index e7c45fe66..000000000 --- a/application/views/scripts/security/update-permission.phtml +++ /dev/null @@ -1,4 +0,0 @@ -
-

translate('Update Permission %s'), $name) ?>

- -
diff --git a/application/views/scripts/security/update-restriction.phtml b/application/views/scripts/security/update-restriction.phtml deleted file mode 100644 index 8766d8658..000000000 --- a/application/views/scripts/security/update-restriction.phtml +++ /dev/null @@ -1,4 +0,0 @@ -
-

translate('Update Restriction %s'), $name) ?>

- -
From f0084542e64936a76bf401e712561ab740965c72 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 14:44:28 +0100 Subject: [PATCH 26/36] Security: Remove obsolete actions refs #5647 --- .../controllers/SecurityController.php | 114 ------------------ 1 file changed, 114 deletions(-) diff --git a/application/controllers/SecurityController.php b/application/controllers/SecurityController.php index 57f228500..5648837f8 100644 --- a/application/controllers/SecurityController.php +++ b/application/controllers/SecurityController.php @@ -4,12 +4,9 @@ use Icinga\Application\Config; use Icinga\Forms\ConfirmRemovalForm; -use Icinga\Forms\Security\PermissionForm; -use Icinga\Forms\Security\RestrictionForm; use Icinga\Forms\Security\RoleForm; use Icinga\Web\Controller\ActionController; use Icinga\Web\Notification; -use Icinga\Web\Request; class SecurityController extends ActionController { @@ -131,115 +128,4 @@ class SecurityController extends ActionController $this->view->name = $name; $this->view->form = $confirmation; } - - public function newRestrictionAction() - { - $restriction = new RestrictionForm(array( - 'onSuccess' => function (Request $request, RestrictionForm $restriction) { - $name = $restriction->getElement('name')->getValue(); - $values = $restriction->getValues(); - try { - $restriction->add($name, $values); - } catch (InvalidArgumentException $e) { - $restriction->addError($e->getMessage()); - return false; - } - if ($restriction->save()) { - Notification::success(t('Restriction set')); - return true; - } - return false; - } - )); - $restriction - ->setIniConfig(Config::app('restrictions', true)) - ->setRedirectUrl('security') - ->handleRequest(); - $this->view->form = $restriction; - } - - public function updateRestrictionAction() - { - $name = $this->_request->getParam('restriction'); - if (empty($name)) { - throw new Zend_Controller_Action_Exception( - sprintf($this->translate('Required parameter \'%s\' missing'), 'restriction'), - 400 - ); - } - $restriction = new RestrictionForm(); - try { - $restriction - ->setIniConfig(Config::app('restrictions', true)) - ->load($name); - } catch (InvalidArgumentException $e) { - throw new Zend_Controller_Action_Exception( - $e->getMessage(), - 400 - ); - } - $restriction - ->setOnSuccess(function (Request $request, RestrictionForm $restriction) use ($name) { - $oldName = $name; - $name = $restriction->getElement('name')->getValue(); - $values = $restriction->getValues(); - try { - $restriction->update($name, $values, $oldName); - } catch (InvalidArgumentException $e) { - $restriction->addError($e->getMessage()); - return false; - } - if ($restriction->save()) { - Notification::success(t('Restriction set')); - return true; - } - return false; - }) - ->setRedirectUrl('security') - ->handleRequest(); - $this->view->name = $name; - $this->view->form = $restriction; - } - - public function removeRestrictionAction() - { - $name = $this->_request->getParam('restriction'); - if (empty($name)) { - throw new Zend_Controller_Action_Exception( - sprintf($this->translate('Required parameter \'%s\' missing'), 'restriction'), - 400 - ); - } - $restriction = new RestrictionForm(); - try { - $restriction - ->setIniConfig(Config::app('restrictions', true)) - ->load($name); - } catch (InvalidArgumentException $e) { - throw new Zend_Controller_Action_Exception( - $e->getMessage(), - 400 - ); - } - $confirmation = new ConfirmRemovalForm(array( - 'onSuccess' => function (Request $request, ConfirmRemovalForm $confirmation) use ($name, $restriction) { - try { - $restriction->remove($name); - } catch (InvalidArgumentException $e) { - Notification::error($e->getMessage()); - return false; - } - if ($restriction->save()) { - Notification::success(sprintf(t('Restriction \'%s\' has been successfully removed'), $name)); - return true; - } - return false; - } - )); - $confirmation - ->setRedirectUrl('security') - ->handleRequest(); - $this->view->name = $name; - $this->view->form = $confirmation; - } } From 0c219655e08bbe59c1b79f1d273173c172f12fbf Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 14:44:53 +0100 Subject: [PATCH 27/36] Security: Our Config object no longer supports __set, __get and so on refs #5647 --- application/forms/Security/RoleForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/forms/Security/RoleForm.php b/application/forms/Security/RoleForm.php index 5861fa6fa..f81cc9fd9 100644 --- a/application/forms/Security/RoleForm.php +++ b/application/forms/Security/RoleForm.php @@ -113,7 +113,7 @@ class RoleForm extends ConfigForm $name )); } - $role = $this->config->{$name}->toArray(); + $role = $this->config->getSection($name)->toArray(); $role['permissions'] = ! empty($role['permissions']) ? String::trimSplit($role['permissions']) : null; From b01a9a65e06e2e1e510dd5fbec622fb26817db4b Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 15:10:09 +0100 Subject: [PATCH 28/36] Security: Introduce AdmissionLoader::getPermissionsAndRestrictions() for loading permissins and restrictions from roles.ini When loading from roles.ini there's currently an empty permission added which is of course a bug and will be fixed asap. refs #5647 --- .../Icinga/Authentication/AdmissionLoader.php | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/library/Icinga/Authentication/AdmissionLoader.php b/library/Icinga/Authentication/AdmissionLoader.php index 65d99f427..4a65d1595 100644 --- a/library/Icinga/Authentication/AdmissionLoader.php +++ b/library/Icinga/Authentication/AdmissionLoader.php @@ -5,6 +5,7 @@ namespace Icinga\Authentication; use Icinga\Application\Config; +use Icinga\Application\Logger; use Icinga\Exception\NotReadableError; use Icinga\Data\ConfigObject; use Icinga\User; @@ -42,6 +43,50 @@ class AdmissionLoader return false; } + /** + * Get user permissions and restrictions + * + * @param User $user + * + * @return array + */ + public function getPermissionsAndRestrictions(User $user) + { + $permissions = array(); + $restrictions = array(); + $username = $user->getUsername(); + try { + $roles = Config::app('roles'); + } catch (NotReadableError $e) { + Logger::error( + 'Can\'t get permissions and restrictions for user \'%s\'. An exception was thrown:', + $username, + $e + ); + return array($permissions, $restrictions); + } + $userGroups = $user->getGroups(); + foreach ($roles as $role) { + if ($this->match($username, $userGroups, $role)) { + $permissions = array_merge( + $permissions, + array_diff(String::trimSplit($role->permissions), $permissions) + ); + $restrictionsFromRole = $role->toArray(); + unset($restrictionsFromRole['users']); + unset($restrictionsFromRole['groups']); + unset($restrictionsFromRole['permissions']); + foreach ($restrictionsFromRole as $name => $restriction) { + if (! isset($restrictions[$name])) { + $restrictions[$name] = array(); + } + $restrictions[$name][] = $restriction; + } + } + } + return array($permissions, $restrictions); + } + /** * Get user permissions * From bed11ebb6000394aff95dbe07c7ec414daa95db4 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 15:11:14 +0100 Subject: [PATCH 29/36] Security: Load user permissions and restrictions from roles.ini refs #5647 --- library/Icinga/Authentication/Manager.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/Icinga/Authentication/Manager.php b/library/Icinga/Authentication/Manager.php index 88258351e..0a9b40981 100644 --- a/library/Icinga/Authentication/Manager.php +++ b/library/Icinga/Authentication/Manager.php @@ -107,8 +107,9 @@ class Manager } $user->setGroups($groups); $admissionLoader = new AdmissionLoader(); - $user->setPermissions($admissionLoader->getPermissions($user)); - $user->setRestrictions($admissionLoader->getRestrictions($user)); + list($permissions, $restrictions) = $admissionLoader->getPermissionsAndRestrictions($user); + $user->setPermissions($permissions); + $user->setRestrictions($restrictions); $this->user = $user; if ($persist) { $this->persistCurrentUser(); From 3e1583ca406b76fc7e1e541434cd99ebac49e5f5 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 15:13:45 +0100 Subject: [PATCH 30/36] Security: Remove getPermissions and getRestrictions from the AdmissionLoader These funtctions are superseded by getRestrictionsAndPermissions. refs #5647 --- .../Icinga/Authentication/AdmissionLoader.php | 70 ------------------- 1 file changed, 70 deletions(-) diff --git a/library/Icinga/Authentication/AdmissionLoader.php b/library/Icinga/Authentication/AdmissionLoader.php index 4a65d1595..d97fc534e 100644 --- a/library/Icinga/Authentication/AdmissionLoader.php +++ b/library/Icinga/Authentication/AdmissionLoader.php @@ -86,74 +86,4 @@ class AdmissionLoader } return array($permissions, $restrictions); } - - /** - * Get user permissions - * - * @param User $user - * - * @return array - */ - public function getPermissions(User $user) - { - $permissions = array(); - try { - $config = Config::app('permissions'); - } catch (NotReadableError $e) { - Logger::error( - 'Can\'t get permissions for user \'%s\'. An exception was thrown:', - $user->getUsername(), - $e - ); - return $permissions; - } - $username = $user->getUsername(); - $userGroups = $user->getGroups(); - foreach ($config as $section) { - if (! empty($section->permissions) - && $this->match($username, $userGroups, $section) - ) { - $permissions = array_merge( - $permissions, - array_diff(String::trimSplit($section->permissions), $permissions) - ); - } - } - return $permissions; - } - - /** - * Get user restrictions - * - * @param User $user - * - * @return array - */ - public function getRestrictions(User $user) - { - $restrictions = array(); - try { - $config = Config::app('restrictions'); - } catch (NotReadableError $e) { - Logger::error( - 'Can\'t get restrictions for user \'%s\'. An exception was thrown:', - $user->getUsername(), - $e - ); - return $restrictions; - } - $username = $user->getUsername(); - $userGroups = $user->getGroups(); - foreach ($config as $section) { - if (! empty($section->restriction) - && $this->match($username, $userGroups, $section) - ) { - $restrictions = array_merge( - $restrictions, - array_diff(String::trimSplit($section->restriction), $restrictions) - ); - } - } - return $restrictions; - } } From 2ae75370f24df74f1800766fe7662812c8c0c626 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 15:18:01 +0100 Subject: [PATCH 31/36] Security: Rename security to permissions refs #5647 --- .../{SecurityController.php => PermissionsController.php} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename application/controllers/{SecurityController.php => PermissionsController.php} (100%) diff --git a/application/controllers/SecurityController.php b/application/controllers/PermissionsController.php similarity index 100% rename from application/controllers/SecurityController.php rename to application/controllers/PermissionsController.php From 5b4c2723e0609e88055a3a518fca56b05dcff5b6 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 15:18:39 +0100 Subject: [PATCH 32/36] Security: Rename security view scripts to permissions refs #5647 --- application/views/scripts/{security => permissions}/index.phtml | 0 .../views/scripts/{security => permissions}/new-role.phtml | 0 .../views/scripts/{security => permissions}/remove-role.phtml | 0 .../views/scripts/{security => permissions}/update-role.phtml | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename application/views/scripts/{security => permissions}/index.phtml (100%) rename application/views/scripts/{security => permissions}/new-role.phtml (100%) rename application/views/scripts/{security => permissions}/remove-role.phtml (100%) rename application/views/scripts/{security => permissions}/update-role.phtml (100%) diff --git a/application/views/scripts/security/index.phtml b/application/views/scripts/permissions/index.phtml similarity index 100% rename from application/views/scripts/security/index.phtml rename to application/views/scripts/permissions/index.phtml diff --git a/application/views/scripts/security/new-role.phtml b/application/views/scripts/permissions/new-role.phtml similarity index 100% rename from application/views/scripts/security/new-role.phtml rename to application/views/scripts/permissions/new-role.phtml diff --git a/application/views/scripts/security/remove-role.phtml b/application/views/scripts/permissions/remove-role.phtml similarity index 100% rename from application/views/scripts/security/remove-role.phtml rename to application/views/scripts/permissions/remove-role.phtml diff --git a/application/views/scripts/security/update-role.phtml b/application/views/scripts/permissions/update-role.phtml similarity index 100% rename from application/views/scripts/security/update-role.phtml rename to application/views/scripts/permissions/update-role.phtml From e072678b2d01064132d86825ae2e0f6b1d75e781 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 15:23:15 +0100 Subject: [PATCH 33/36] Security: Remove role suffix from actions refs #5647 --- application/controllers/PermissionsController.php | 6 +++--- application/views/scripts/permissions/index.phtml | 6 +++--- .../views/scripts/permissions/{new-role.phtml => new.phtml} | 0 .../scripts/permissions/{remove-role.phtml => remove.phtml} | 0 .../scripts/permissions/{update-role.phtml => update.phtml} | 0 5 files changed, 6 insertions(+), 6 deletions(-) rename application/views/scripts/permissions/{new-role.phtml => new.phtml} (100%) rename application/views/scripts/permissions/{remove-role.phtml => remove.phtml} (100%) rename application/views/scripts/permissions/{update-role.phtml => update.phtml} (100%) diff --git a/application/controllers/PermissionsController.php b/application/controllers/PermissionsController.php index 5648837f8..9161553a2 100644 --- a/application/controllers/PermissionsController.php +++ b/application/controllers/PermissionsController.php @@ -15,7 +15,7 @@ class SecurityController extends ActionController $this->view->roles = Config::app('roles', true); } - public function newRoleAction() + public function newAction() { $role = new RoleForm(array( 'onSuccess' => function (RoleForm $role) { @@ -42,7 +42,7 @@ class SecurityController extends ActionController $this->view->form = $role; } - public function updateRoleAction() + public function updateAction() { $name = $this->_request->getParam('role'); if (empty($name)) { @@ -86,7 +86,7 @@ class SecurityController extends ActionController $this->view->form = $role; } - public function removeRoleAction() + public function removeAction() { $name = $this->_request->getParam('role'); if (empty($name)) { diff --git a/application/views/scripts/permissions/index.phtml b/application/views/scripts/permissions/index.phtml index 3dc571ce9..520f42d1a 100644 --- a/application/views/scripts/permissions/index.phtml +++ b/application/views/scripts/permissions/index.phtml @@ -19,14 +19,14 @@ escape($name) ?> escape($role->permissions) ?> escape($role->users) ?> escape($role->groups) ?> - + translate('Remove role') ?> @@ -35,7 +35,7 @@ - + translate('New Role') ?> diff --git a/application/views/scripts/permissions/new-role.phtml b/application/views/scripts/permissions/new.phtml similarity index 100% rename from application/views/scripts/permissions/new-role.phtml rename to application/views/scripts/permissions/new.phtml diff --git a/application/views/scripts/permissions/remove-role.phtml b/application/views/scripts/permissions/remove.phtml similarity index 100% rename from application/views/scripts/permissions/remove-role.phtml rename to application/views/scripts/permissions/remove.phtml diff --git a/application/views/scripts/permissions/update-role.phtml b/application/views/scripts/permissions/update.phtml similarity index 100% rename from application/views/scripts/permissions/update-role.phtml rename to application/views/scripts/permissions/update.phtml From 63490094b98d7bfabec7b1cf20328039cd5067a5 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 15:24:57 +0100 Subject: [PATCH 34/36] Security: Fix PermissionsController class name refs #5647 --- application/controllers/PermissionsController.php | 2 +- application/views/scripts/permissions/index.phtml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/application/controllers/PermissionsController.php b/application/controllers/PermissionsController.php index 9161553a2..effd80852 100644 --- a/application/controllers/PermissionsController.php +++ b/application/controllers/PermissionsController.php @@ -8,7 +8,7 @@ use Icinga\Forms\Security\RoleForm; use Icinga\Web\Controller\ActionController; use Icinga\Web\Notification; -class SecurityController extends ActionController +class PermissionsController extends ActionController { public function indexAction() { diff --git a/application/views/scripts/permissions/index.phtml b/application/views/scripts/permissions/index.phtml index 520f42d1a..8918cdd46 100644 --- a/application/views/scripts/permissions/index.phtml +++ b/application/views/scripts/permissions/index.phtml @@ -1,8 +1,8 @@
-

translate('Roles') ?>

+

translate('Permissions') ?>

isEmpty()): ?> - translate('No roles found.') ?> + translate('No permissions found.') ?> From 1db85a745a4dc95e772c27ed8f267a1360f4cc61 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 15:25:43 +0100 Subject: [PATCH 35/36] Monitoring: Provide command permissions refs #5647 --- modules/monitoring/configuration.php | 54 ++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/modules/monitoring/configuration.php b/modules/monitoring/configuration.php index 366067c09..d61e32858 100644 --- a/modules/monitoring/configuration.php +++ b/modules/monitoring/configuration.php @@ -2,14 +2,54 @@ // {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}} -/* @var $this \Icinga\Application\Modules\Module */ +/** @var $this \Icinga\Application\Modules\Module */ + +$this->providePermission( + 'monitoring/command/*', + $this->translate('Allow all commands') +); +$this->providePermission( + 'monitoring/command/schedule*', + $this->translate('Allow all scheduling checks and downtimes') +); +$this->providePermission( + 'monitoring/command/schedule-check', + $this->translate('Allow scheduling host and service checks') +); +$this->providePermission( + 'monitoring/command/schedule-downtime', + $this->translate('Allow scheduling host and service downtimes') +); +$this->providePermission( + 'monitoring/command/acknowledge-problem', + $this->translate('Allow acknowledging host and service problems') +); +$this->providePermission( + 'monitoring/command/add-comment', + $this->translate('Allow commenting on hosts and services') +); +$this->providePermission( + 'monitoring/command/remove*', + $this->translate('Allow removing problem acknowledgements, host and service comments and downtimes') +); +$this->providePermission( + 'monitoring/command/remove-acknowledgement', + $this->translate('Allow removing problem acknowledgements') +); +$this->providePermission( + 'monitoring/command/remove-comment', + $this->translate('Allow removing host and service comments') +); +$this->providePermission( + 'monitoring/command/remove-downtime', + $this->translate('Allow removing host and service downtimes') +); + +$this->provideRestriction( + 'monitoring/filter', + $this->translate('Restrict views to the hosts and services that match the filter') +); -// TODO: We need to define a useful permission set for this module, the -// list provided here is just an example -$this->providePermission('commands/all', 'Allow to send all commands'); -$this->providePermission('commands/safe', 'Allow to to send a subset of "safe" commands'); -$this->providePermission('log', 'Allow full log access'); -$this->provideRestriction('filter', 'Filter accessible object'); $this->provideConfigTab('backends', array( 'title' => 'Backends', 'url' => 'config' From bfdf34b6bf88ffd12956eddfd12abf7a4af90067 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 19 Nov 2014 15:32:25 +0100 Subject: [PATCH 36/36] Security: Add permissions as tab to config refs #5647 --- application/controllers/ConfigController.php | 9 ++++++--- .../controllers/PermissionsController.php | 19 +++++++++++++++++++ .../views/scripts/permissions/index.phtml | 3 +++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php index 8f5f9eb42..73d40261c 100644 --- a/application/controllers/ConfigController.php +++ b/application/controllers/ConfigController.php @@ -24,14 +24,17 @@ class ConfigController extends ActionController public function init() { $this->view->tabs = Widget::create('tabs')->add('index', array( - 'title' => 'Application', + 'title' => $this->translate('Application'), 'url' => 'config' ))->add('authentication', array( - 'title' => 'Authentication', + 'title' => $this->translate('Authentication'), 'url' => 'config/authentication' ))->add('resources', array( - 'title' => 'Resources', + 'title' => $this->translate('Resources'), 'url' => 'config/resource' + ))->add('permissions', array( + 'title' => $this->translate('Permissions'), + 'url' => 'permissions' )); } diff --git a/application/controllers/PermissionsController.php b/application/controllers/PermissionsController.php index effd80852..8709a28ad 100644 --- a/application/controllers/PermissionsController.php +++ b/application/controllers/PermissionsController.php @@ -7,11 +7,30 @@ use Icinga\Forms\ConfirmRemovalForm; use Icinga\Forms\Security\RoleForm; use Icinga\Web\Controller\ActionController; use Icinga\Web\Notification; +use Icinga\Web\Widget; class PermissionsController extends ActionController { + public function init() + { + $this->view->tabs = Widget::create('tabs')->add('index', array( + 'title' => $this->translate('Application'), + 'url' => 'config' + ))->add('authentication', array( + 'title' => $this->translate('Authentication'), + 'url' => 'config/authentication' + ))->add('resources', array( + 'title' => $this->translate('Resources'), + 'url' => 'config/resource' + ))->add('permissions', array( + 'title' => $this->translate('Permissions'), + 'url' => 'permissions' + )); + } + public function indexAction() { + $this->view->tabs->activate('permissions'); $this->view->roles = Config::app('roles', true); } diff --git a/application/views/scripts/permissions/index.phtml b/application/views/scripts/permissions/index.phtml index 8918cdd46..285d2f894 100644 --- a/application/views/scripts/permissions/index.phtml +++ b/application/views/scripts/permissions/index.phtml @@ -1,3 +1,6 @@ +
+ +

translate('Permissions') ?>