Icinga / icingaweb2

A lightweight and extensible web interface to keep an eye on your environment. Analyse problems and act on them.
https://icinga.com/get-started/
GNU General Public License v2.0
809 stars 282 forks source link

Nested Groups break the directory browsing #3935

Open slalomsk8er opened 5 years ago

slalomsk8er commented 5 years ago

Describe the bug

We use nested AD-Groups to manage the logins and roles.

Logins and roles works well but /icingaweb2/group/show doesn't differentiate between members of type group and user, it assumes type user and if I click on the member of type group I get the following error:

User "ggSpectrumAdmins" not found

#0 /usr/share/php/Icinga/Exception/IcingaException.php(41): ReflectionClass->newInstanceArgs(Array)
#1 /usr/share/php/Icinga/Web/Controller.php(87): Icinga\Exception\IcingaException::create(Array)
#2 /usr/share/icingaweb2/application/controllers/UserController.php(104): Icinga\Web\Controller->httpNotFound(String)
#3 /usr/share/icingaweb2/library/vendor/Zend/Controller/Action.php(507): Icinga\Controllers\UserController->showAction()
#4 /usr/share/php/Icinga/Web/Controller/Dispatcher.php(76): Zend_Controller_Action->dispatch(String)
#5 /usr/share/icingaweb2/library/vendor/Zend/Controller/Front.php(937): Icinga\Web\Controller\Dispatcher->dispatch(Object(Icinga\Web\Request), Object(Icinga\Web\Response))
#6 /usr/share/php/Icinga/Application/Web.php(300): Zend_Controller_Front->dispatch(Object(Icinga\Web\Request), Object(Icinga\Web\Response))
#7 /usr/share/php/Icinga/Application/webrouter.php(99): Icinga\Application\Web->dispatch()
#8 /usr/share/icingaweb2/public/index.php(4): require_once(String)
#9 {main}

This is logical as the URL wants to open the child group as a user: https://icinga/icingaweb2/group/show?backend=auth_ad&group=ICT_P_Icinga_Spectrum_Admin#!/icingaweb2/user/show?backend=auth_ad&user=ggSpectrumAdmins

If I manipulate the URL by hand it works: https://icinga/icingaweb2/group/show?backend=auth_ad&group=ICT_P_Icinga_Spectrum_Admin#!/icingaweb2/group/show?backend=auth_ad&group=ggSpectrumAdmins

To Reproduce

  1. Use the AD-Backend with a AGDLP schema (business groups in permission groups).
  2. Enable Nested Group Search.
  3. Browse https://icinga/icingaweb2/group/list click on a member of a group that is itself a group.

Expected behavior

Browsing groups differentiates between type user and group and chooses the correct view accordingly without presenting errors and/or needing manipulation of the URL by hand.

nilmerg commented 5 years ago

Hi, thanks for the report. This is not a bug nor something with an easy solution. The directory browsing is part of a generic solution for user and group browsing which is incapable of handling nested groups and was unfortunately never designed to do so.

It's also a long standing case and you're the first reporting this. (I guess others use dedicated tools to browse their directories) Due to that I can't see us taking action on this very soon. If anybody has interest we're open for contributions, though.

slalomsk8er commented 5 years ago

Interesting, I would like to have a go at it. Do you have any pointers on where to start adding a differentiator between users and groups and where I would need to switch the URLs for the respecting case?

nilmerg commented 5 years ago

The urls are made here. There's also a corresponding script for group/list a level up.

The differentiator is the tricky part. You'll need to implement a way to distinguish users and groups for ldap backends. All other group backends however also need to support this, albeit they don't need to provide a differentiator if there are no nested groups possible. (e.g. for the database that's the case)

Key is to teach the generic views that there may be groups within groups, but not all backend types really provide groups within groups. Only the ldap backend really provides a way to distinguish groups from users when being asked for users. Got it? :laughing:

netphantm commented 4 years ago

I think it should either just list users as it currently claims to do by expanding all subgroups (it clearly says "Username" on top of the list - see screenshot), or show another list for groups if you want to also search the nested groups for users. For now my problem is, it doesn't list all users in the nested groups if nested_group_search is set to "1" in the config. I even tried to set the filter in groups.ini to something like this:

group_filter="memberof:1.2.840.113556.1.4.1941:=CN=ALL_Monitoring,OU=Internal,OU=Monitoring,OU=SystemAccess,OU=Groups,DC=int,DC=example,DC=com"

but it doesn't use it when searching the requested group to get the members (users), see the following log excerpt:

2020-02-19T10:14:15+01:00 - DEBUG - Issuing LDAP search. Use 'ldapsearch -P 3 -H "ldaps://directory.int.example.com:636" -D "CN=nagios,OU=Service Accounts,DC=int,DC=example,DC=com" -W -b "OU=Internal,OU=Monitoring,OU=SystemAccess,OU=Groups,DC=int,DC=example,DC=com" -s "sub" -z 1 -l 0 -a "never" "(&(memberof:1.2.840.113556.1.4.1941:=CN=ALL Monitoring,OU=Internal,OU=Monitoring,OU=SystemAccess,OU=Groups,DC=int,DC=example,DC=com)(&(objectClass=group)(sAMAccountName=Monitoring IT-Services)))" "sAMAccountName" "whenCreated" "whenChanged"' to reproduce.< correct filter

2020-02-19T10:14:15+01:00 - DEBUG - Issuing LDAP search. Use 'ldapsearch -P 3 -H "ldaps://directory.int.example.com:636" -D "CN=nagios,OU=Service Accounts,DC=int,DC=example,DC=com" -W -b "OU=Internal,OU=Monitoring,OU=SystemAccess,OU=Groups,DC=int,DC=example,DC=com" -s "sub" -z 0 -l 0 -a "never" "(&(objectClass=group)(sAMAccountName=Monitoring IT-Services))" "member" "objectClass" "sAMAccountName"' to reproduce. < wrong filter

2020-02-19T10:14:15+01:00 - DEBUG - Issuing LDAP search. Use 'ldapsearch -P 3 -H "ldaps://directory.int.example.com:636" -D "CN=nagios,OU=Service Accounts,DC=int,DC=example,DC=com" -W -b "OU=Internal,OU=Monitoring,OU=SystemAccess,OU=Groups,DC=int,DC=example,DC=com" -s "sub" -z 25 -l 0 -a "never" "(&(objectClass=group)(sAMAccountName=Monitoring IT-Services))" "member" "objectClass" "sAMAccountName"' to reproduce. < wrong filter

2020-02-19T10:14:15+01:00 - DEBUG - Issuing LDAP search. Use 'ldapsearch -P 3 -H "ldaps://directory.int.example.com:636" -D "CN=nagios,OU=Service Accounts,DC=int,DC=example,DC=com" -W -b "CN=BLi,CN=Users,DC=int,DC=example,DC=com" -s "sub" -z 1 -l 0 -a "never" "(objectClass=*)" "sAMAccountName"' to reproduce.

2020-02-19T10:14:15+01:00 - DEBUG - Issuing LDAP search. Use 'ldapsearch -P 3 -H "ldaps://directory.int.example.com:636" -D "CN=nagios,OU=Service Accounts,DC=int,DC=example,DC=com" -W -b "CN=AdA,CN=Users,DC=int,DC=example,DC=com" -s "sub" -z 1 -l 0 -a "never" "(objectClass=*)" "sAMAccountName"' to reproduce.

2020-02-19T10:14:15+01:00 - DEBUG - Issuing LDAP search. Use 'ldapsearch -P 3 -H "ldaps://directory.int.example.com:636" -D "CN=nagios,OU=Service Accounts,DC=int,DC=example,DC=com" -W -b "CN=ALL IT-Services,OU=IT-Services,OU=Departments,OU=Groups,DC=int,DC=example,DC=com" -s "sub" -z 1 -l 0 -a "never" "(objectClass=*)" "sAMAccountName"' to reproduce.

In the last 3 lines, it shoud use another filter, to show only users: (objectClass=user) instead of (objectClass=*).

We currently use a perl script that generates the roles.ini file from AD groups at midday and midnight (including users from nested groups). I thought that by using AD/LDAP instead of external (apache) authentication, I could get rid of that script and set permissions based on the AD groups in the roles.ini file by using groups="Monitoring IT-Services" instead of users="ada,bli" line from roles.ini). But for that to work, another change would also be necessary, which is outside of the scope of this issue.