From 8a604f1c2c335bd9488409a55db29ad324801d23 Mon Sep 17 00:00:00 2001 From: Marius Hein Date: Wed, 12 Feb 2014 17:01:11 +0100 Subject: [PATCH] Implement structures for permissions, restrictions and membership refs #4624 --- config/membership.ini | 9 ++ config/permissions.ini | 11 ++ config/restrictions.ini | 16 +++ .../Icinga/Authentication/AdmissionLoader.php | 108 ++++++++++++++++++ library/Icinga/Authentication/Manager.php | 22 +++- library/Icinga/Authentication/Membership.php | 59 ++++++++++ library/Icinga/User.php | 82 ++++--------- library/Icinga/Util/String.php | 49 ++++++++ 8 files changed, 290 insertions(+), 66 deletions(-) create mode 100644 config/membership.ini create mode 100644 config/permissions.ini create mode 100644 config/restrictions.ini create mode 100644 library/Icinga/Authentication/AdmissionLoader.php create mode 100644 library/Icinga/Authentication/Membership.php create mode 100644 library/Icinga/Util/String.php diff --git a/config/membership.ini b/config/membership.ini new file mode 100644 index 000000000..c92fae47c --- /dev/null +++ b/config/membership.ini @@ -0,0 +1,9 @@ +[membership-set1] +backend = groupX +users = icingaadmin,tgelf +groups = admin,users + +[membership-set2] +backend = groupY +users = icingaadmin +groups = support1,support2 diff --git a/config/permissions.ini b/config/permissions.ini new file mode 100644 index 000000000..3fec92f1c --- /dev/null +++ b/config/permissions.ini @@ -0,0 +1,11 @@ +[test1] +users = icingaadmin,root,tgelf +groups = support2,support2 +permission_1 = monitoring, monitoring/log +permission_2 = monitoring/command/all + +[test2] +users = root +groups = admin +permission_2 = test/permission/1, test/permission/2 +permission_3 = test/permission/15, test/permission/7 \ No newline at end of file diff --git a/config/restrictions.ini b/config/restrictions.ini new file mode 100644 index 000000000..d180a0174 --- /dev/null +++ b/config/restrictions.ini @@ -0,0 +1,16 @@ +[test1] +users = "tgelf" +groups = "support2" +name = "monitoring/filter" +restriction = "hostgroup=lalala&service_description=*ping*" + +[test2] +users = "icingaadmin123123" +name = "monitoring/filter" +restriction = "hostgroup=kunden*&service_description=*ping*" + +[test3] +users = "icingaadmin" +name = "monitoring/filter" +restriction = "hostgroup=kunden*&service_description=*ping-ping*" + diff --git a/library/Icinga/Authentication/AdmissionLoader.php b/library/Icinga/Authentication/AdmissionLoader.php new file mode 100644 index 000000000..e8e5f6a16 --- /dev/null +++ b/library/Icinga/Authentication/AdmissionLoader.php @@ -0,0 +1,108 @@ + + * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 + * @author Icinga Development Team + * + */ +// {{{ICINGA_LICENSE_HEADER}}}} + +namespace Icinga\Authentication; + +use Icinga\Application\Config; +use Icinga\Util\String; + +/** + * Retrieve restrictions and permissions for users + */ +class AdmissionLoader +{ + /** + * Match against groups + * + * @param string $section + * @param string $username + * @param array $groups + * + * @return bool + */ + private function match($section, $username, array $groups) + { + if ($section->users && in_array($username, String::trimSplit($section->users)) === true) { + return true; + } + + if ($section->groups && count(array_intersect(String::trimSplit($section->groups), $groups)) > 0) { + return true; + } + + return false; + } + + /** + * Retrieve permissions + * + * @param string $username + * @param array $groups + * + * @return array + */ + public function getPermissions($username, array $groups) + { + $permissions = array(); + foreach (Config::app('permissions') as $section) { + if ($this->match($section, $username, $groups)) { + foreach ($section as $key => $value) { + if (strpos($key, 'permission') === 0) { + $permissions = array_merge($permissions, String::trimSplit($value)); + } + } + } + } + + return $permissions; + } + + /** + * Retrieve restrictions + * + * @param $username + * @param array $groups + * + * @return array + */ + public function getRestrictions($username, array $groups) + { + $restrictions = array(); + foreach (Config::app('restrictions') as $section) { + if ($this->match($section, $username, $groups)) { + if (array_key_exists($section->name, $restrictions) === false) { + $restrictions[$section->name] = array(); + } + $restrictions[$section->name][] = $section->restriction; + } + } + + return $restrictions; + } +} diff --git a/library/Icinga/Authentication/Manager.php b/library/Icinga/Authentication/Manager.php index 45e8bd566..53154651f 100644 --- a/library/Icinga/Authentication/Manager.php +++ b/library/Icinga/Authentication/Manager.php @@ -40,7 +40,6 @@ use Icinga\Application\Config as IcingaConfig; use Icinga\Authentication\Backend\DbUserBackend; use Icinga\Authentication\Backend\LdapUserBackend; - /** * The authentication manager allows to identify users and * to persist authentication information in a session. @@ -345,11 +344,22 @@ class Manager return false; } - // TODO: We want to separate permissions and restrictions from - // the user object. This will be possible once session - // had been refactored. - $this->user->loadPermissions(); - $this->user->loadRestrictions(); + $username = $credentials->getUsername(); + + $membership = new Membership(); + + $groups = $membership->getGroupsByUsername($username); + $this->user->setGroups($groups); + + $admissionLoader = new AdmissionLoader(); + + $this->user->setPermissions( + $admissionLoader->getPermissions($username, $groups) + ); + + $this->user->setRestrictions( + $admissionLoader->getRestrictions($username, $groups) + ); if ($persist == true) { $this->persistCurrentUser(); diff --git a/library/Icinga/Authentication/Membership.php b/library/Icinga/Authentication/Membership.php new file mode 100644 index 000000000..fd6141c5b --- /dev/null +++ b/library/Icinga/Authentication/Membership.php @@ -0,0 +1,59 @@ + + * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 + * @author Icinga Development Team + * + */ +// {{{ICINGA_LICENSE_HEADER}}}} + +namespace Icinga\Authentication; + +use Icinga\Application\Config; +use Icinga\Util\String; + +/** + * Retrieve membership information for users and group + */ +class Membership +{ + /** + * Return a list of groups for an username + * + * @param string $username + * + * @return array + */ + public function getGroupsByUsername($username) + { + $groups = array(); + foreach (Config::app('membership') as $section) { + $users = String::trimSplit($section->users); + + if (in_array($username, $users) === true) { + $groups = array_merge($groups, String::trimSplit($section->groups)); + } + } + return $groups; + } +} diff --git a/library/Icinga/User.php b/library/Icinga/User.php index ba0c98f5f..94ce4c6b9 100644 --- a/library/Icinga/User.php +++ b/library/Icinga/User.php @@ -205,10 +205,21 @@ class User return $this->permissions; } + /** + * Setter for permissions + * + * @param array $permissions + */ + public function setPermissions(array $permissions) + { + $this->permissions = $permissions; + } + /** * Return restriction information for this user * - * @return Array + * @param string $name + * @return array */ public function getRestrictions($name) { @@ -218,6 +229,16 @@ class User return array(); } + /** + * Settter for restrictions + * + * @param array $restrictions + */ + public function setRestrictions(array $restrictions) + { + $this->restrictions = $restrictions; + } + /** * Getter for username * @@ -323,65 +344,6 @@ class User return $this->domain; } - /** - * Load permissions for this user from permissions.ini - * - * TODO: - Separate this from the user object once possible - * - Support group permissions once groups are available - * - * @return self - */ - public function loadPermissions() - { - try { - // TODO: Config::app should gracefully handle missing files - $config = Config::app('permissions'); - } catch (Exception $e) { - return $this; - } - foreach ($config as $section) { - if ($section->get('user') !== $this->username) { - continue; - } - foreach ($section->toArray() as $key => $val) { - if (false !== ($pos = strpos($key, '_')) - && substr($key, 0, $pos) === 'permission') - { - $this->permissions[] = $val; - } - } - } - return $this; - } - - /** - * Load restrictions for this user from restrictions.ini - * - * TODO: - Separate this from the user object once possible - * - Support group restrictions once groups are available - * - * @return self - */ - public function loadRestrictions() - { - try { - // TODO: Config::app should gracefully handle missing files - $config = Config::app('restrictions'); - } catch (Exception $e) { - return $this; - } - - foreach ($config as $section) { - if ($section->get('user') !== $this->username) { - continue; - } - if (! array_key_exists($section->name, $this->restrictions)) { - $this->restrictions[$section->name] = array(); - } - $this->restrictions[$section->name][] = $section->restriction; - } - return $this; - } /** * Set additional information about user diff --git a/library/Icinga/Util/String.php b/library/Icinga/Util/String.php new file mode 100644 index 000000000..08ebf6277 --- /dev/null +++ b/library/Icinga/Util/String.php @@ -0,0 +1,49 @@ + + * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 + * @author Icinga Development Team + * + */ +// {{{ICINGA_LICENSE_HEADER}}} + +namespace Icinga\Util; + +/** + * Common string helper + */ +class String +{ + /** + * Split string into an array and trim spaces + * + * @param string $value + * @param string $delimiter + * + * @return array + */ + public static function trimSplit($value, $delimiter = ',') + { + return array_map('trim', explode(',', $value)); + } +}