-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
user_ldap: Filter groups after nested groups #8227
Conversation
Currently groupsMatchFilter is called before nested groups are resolved. This basicly breaks this feature since it is not possible to inherit membership in a group from another group. Minimal example: Group filter: (&(objectClass=group),(cn=nextcloud)) Nested groups: enabled cn=nextcloud,ou=Nextcloud,ou=groups,dn=company,dn=local objectClass: group cn=IT,ou=groups,dn=company,dn=local objectClass: group memberOf: cn=nextcloud,ou=Nextcloud,ou=groups,dn=company,dn=local cn=John Doe,ou=users,dn=company,dn=local objectClass: person memberOf: cn=IT,ou=groups,dn=company,dn=local Since 'cn=IT,ou=groups,dn=company,dn=local' doesn't match the group filter, John wouldn't be a member of group 'nextcloud'. This patch fixes this by filtering the groups after all nested groups have been collected. If nested groups is disabled the result will be the same as without this patch. Signed-off-by: Roland Tapken <[email protected]>
Sorry, this patch is incomplete. It only works for one level on indirection and fails if there is a second level:
I'll see if I can rewrite the patch and push it. |
The previous patch fixed the problem only for one level of indirection because groupsMatchFilter() had been applied on each recursive call (and thus there would be no second level if the first level fails the check). This new implementation replaces the recursive call with a stack that iterates all nested groups before filtering with groupsMatchFilter(). Signed-off-by: Roland Tapken <[email protected]>
The updated pull request is a more complex change, but it ensures that nested groups are resolved until their root. |
Nested groups are now cached in a CappedMemoryCache object to reduce queries to the LDAP backend. Signed-off-by: Roland Tapken <[email protected]>
Codecov Report
@@ Coverage Diff @@
## master #8227 +/- ##
============================================
- Coverage 52.75% 51.69% -1.07%
- Complexity 24062 25392 +1330
============================================
Files 1506 1599 +93
Lines 90305 95122 +4817
Branches 1376 1376
============================================
+ Hits 47643 49175 +1532
- Misses 42662 45947 +3285
|
…anymore. Signed-off-by: Roland Tapken <[email protected]>
@nextcloud/ldap Could you please have a look at this? It's already lying around for too long. |
Yes, when the filter is as strict as that. With this changes, the filter does not apply to the subgroups so their members are being read despite that they are not whitelisted. |
@blizzz Thanks for your feedback. No, the filter is still applied to the subgroups, but only at the end after all sub groups have been resolved. This is the only way to allow the usage of "transparent" distributions groups (like "IT" and "Administrator" in the example) that are common in larger Active Directory configurations. |
@Cybso that's my point. It allows members of those groups to be retrieved while the groups themselves are not white listed. I am sure it makes sense from one point of view, but rather not from another and constitutes a behavioural change. Further more, the better approach is perhaps to solely rely on LDAP_MATCHING_RULE_IN_CHAIN so that the LDAP server resolves the the subgroups. I never tested it with OpenLDAP, however it would also be the better performing approach. |
@blizzz This is not for members of groups but for memberships of a user, and even if the intermediate groups are not listed the user is a member of the groups at the leaves. LDAP_MATCHING_RULE_IN_CHAIN resolves the members of a group recursively, but in this case the opposite is required (get all groups where a person is member of, direct or indirect) and as far as I know there is no search syntax that provides this feature besides to recursively climb down the tree. In other words: the user will be listed when querying for the group's member with LDAP_MATCHING_RULE_IN_CHAIN, so _getGroupDNsFromMemberOf($DN) should return the group, too. |
Ah, excuse me, I was mentally in another place of the code 🙊
True. Can I ask also here for unit tests? TestCase offers |
@blizzz Should we take it as it is or wait longer? |
I am very sorry, but at the moment I am extremely busy both professionally and privately, so I did not have the time to do that and probably will not find an opportunity to get into the test framework in the foreseeable future. See also #8230 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have some nitpicks but it is essentially done. I'd look into it when i am back. It's to the most degree also a bug fix, so should not be affected by the freeze for 16 imho.
$seen[$group] = 1; | ||
|
||
// Resolve nested groups | ||
if (isset($cachedNestedGroups[$group])) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be $this->cachedNestedGroups[$group]
|
||
// Resolve nested groups | ||
if (isset($cachedNestedGroups[$group])) { | ||
$nestedGroups = $cachedNestedGroups[$group]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here as well
if (!is_array($nestedGroups)) { | ||
$nestedGroups = []; | ||
} | ||
$cachedNestedGroups[$group] = $nestedGroups; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and here
} | ||
$cachedNestedGroups[$group] = $nestedGroups; | ||
} | ||
foreach ($nestedGroups as $nestedGroup) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can be simplified with an array_merge if i am not mistaken
} | ||
// Get unique group DN's from those we have visited in the loop | ||
$groups = array_keys($seen); |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
I took over, (extended) follow up PR is #14464 |
Currently groupsMatchFilter is called before nested groups are resolved.
This basicly breaks this feature since it is not possible to inherit
membership in a group from another group.
Minimal example:
Since 'cn=IT,ou=groups,dn=company,dn=local' doesn't match the group
filter, John wouldn't be a member of group 'nextcloud'.
This patch fixes this by filtering the groups after all nested groups
have been collected. If nested groups is disabled the result will be the
same as without this patch.
Signed-off-by: Roland Tapken [email protected]