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/+/960683
Depends-on: https://review.opendev.org/c/openstack/devstack/+/960684
Change-Id: I9707e1a9bc4a334902933d6251888144f8c3bc19
Signed-off-by: Jorge Merlino <jorge.merlino@canonical.com>
(cherry picked from commit f8338be430)
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user