Fix AD nested groups issues

The implementation of AD nested groups searches works fine when
listing the groups a user belongs to, but fails when listing all
members of a group. This function of listing all members is also
used to check if a user belongs to a group which also fails.
This patch fixes the query for getting all users in a group.

Closes-Bug: #2112477

Depends-on: https://review.opendev.org/c/openstack/devstack/+/953569
Depends-on: https://review.opendev.org/c/openstack/devstack/+/954914

Change-Id: I9707e1a9bc4a334902933d6251888144f8c3bc19
Signed-off-by: Jorge Merlino <jorge.merlino@canonical.com>
This commit is contained in:
Jorge Merlino 2025-06-04 13:58:17 -03:00
parent 069fa4566b
commit f8338be430
2 changed files with 21 additions and 7 deletions

View file

@ -1417,6 +1417,12 @@ class BaseLdap:
self.auth_pool_conn_lifetime = conf.ldap.auth_pool_connection_lifetime
if self.options_name is not None:
self.user_tree_dn = (
conf.ldap.user_tree_dn
or f'{self.DEFAULT_OU},{conf.ldap.suffix}'
)
self.user_objectclass = conf.ldap.user_objectclass
self.tree_dn = (
getattr(conf.ldap, f'{self.options_name}_tree_dn')
or f'{self.DEFAULT_OU},{conf.ldap.suffix}'
@ -1854,9 +1860,14 @@ class BaseLdap:
return self._filter_ldap_result_by_attr(res, 'name')
def _ldap_get_list(
self, search_base, scope, query_params=None, attrlist=None
self,
search_base,
scope,
query_params=None,
attrlist=None,
object_class=None,
):
query = f'(objectClass={self.object_class})'
query = f'(objectClass={object_class or self.object_class})'
if query_params:
def calc_filter(attrname, value):

View file

@ -434,23 +434,26 @@ class GroupApi(common_ldap.BaseLdap):
"""Return a list of user dns which are members of a group."""
group_ref = self.get(group_id)
group_dn = group_ref['dn']
attribute = self.member_attribute
try:
if self.group_ad_nesting:
# NOTE(ayoung): LDAP_SCOPE is used here instead of hard-
# coding to SCOPE_SUBTREE to get through the unit tests.
# However, it is also probably more correct.
attribute = "distinguishedName"
attrs = self._ldap_get_list(
self.tree_dn,
self.user_tree_dn,
self.LDAP_SCOPE,
query_params={
f"member:{LDAP_MATCHING_RULE_IN_CHAIN}:": group_dn
f"memberOf:{LDAP_MATCHING_RULE_IN_CHAIN}:": group_dn
},
attrlist=[self.member_attribute],
attrlist=[attribute],
object_class=self.user_objectclass,
)
else:
attrs = self._ldap_get_list(
group_dn, ldap.SCOPE_BASE, attrlist=[self.member_attribute]
group_dn, ldap.SCOPE_BASE, attrlist=[attribute]
)
except ldap.NO_SUCH_OBJECT:
@ -458,7 +461,7 @@ class GroupApi(common_ldap.BaseLdap):
users = []
for dn, member in attrs:
user_dns = member.get(self.member_attribute, [])
user_dns = member.get(attribute, [])
for user_dn in user_dns:
users.append(user_dn)
return users