@@ -71,6 +71,9 @@ def __init__(self, caller_options):
71
71
builder .set_string_value ('group_member_filter_format' , six .text_type (
72
72
'(memberOf={group_dn})' ))
73
73
builder .set_bool_value ('require_tls_cert' , False )
74
+ builder .set_bool_value ('two_steps_group_member_lookup' , False )
75
+ builder .set_string_value ('two_steps_group_member_attribute_name' , 'member' )
76
+ builder .set_string_value ('user_identity_type_format' , None )
74
77
builder .set_string_value ('string_encoding' , 'utf8' )
75
78
builder .set_string_value ('user_identity_type_format' , None )
76
79
builder .set_string_value ('user_email_format' , six .text_type ('{mail}' ))
@@ -132,28 +135,42 @@ def load_users_and_groups(self, groups, extended_attributes, all_users):
132
135
options = self .options
133
136
all_users_filter = six .text_type (options ['all_users_filter' ])
134
137
group_member_filter_format = six .text_type (options ['group_member_filter_format' ])
138
+ two_steps_group_member_lookup = six .text_type (options ['two_steps_group_member_lookup' ])
139
+ two_steps_group_member_attribute_name = six .text_type (options ['two_steps_group_member_attribute_name' ])
140
+
141
+ # save all the users to memory for faster 2-steps lookup process
142
+ if two_steps_group_member_lookup :
143
+ all_users_records = dict (self .iter_users (all_users_filter , extended_attributes ))
135
144
136
145
# for each group that's required, do one search for the users of that group
137
146
for group in groups :
138
- group_dn = self .find_ldap_group_dn (group )
139
- if not group_dn :
140
- self .logger .warning ("No group found for: %s" , group )
141
- continue
142
- group_member_subfilter = self .format_ldap_query_string (group_member_filter_format , group_dn = group_dn )
143
- if not group_member_subfilter .startswith ('(' ):
144
- group_member_subfilter = six .text_type ('(' ) + group_member_subfilter + six .text_type (')' )
145
- user_subfilter = all_users_filter
146
- if not user_subfilter .startswith ('(' ):
147
- user_subfilter = six .text_type ('(' ) + user_subfilter + six .text_type (')' )
148
- group_user_filter = six .text_type ('(&' ) + group_member_subfilter + user_subfilter + six .text_type (')' )
149
147
group_users = 0
150
- try :
151
- for user_dn , user in self .iter_users (group_user_filter , extended_attributes ):
152
- user ['groups' ].append (group )
153
- group_users += 1
154
- self .logger .debug ('Count of users in group "%s": %d' , group , group_users )
155
- except Exception as e :
156
- raise AssertionException ('Unexpected LDAP failure reading group members: %s' % e )
148
+ if not two_steps_group_member_lookup :
149
+ group_dn = self .find_ldap_group_dn (group )
150
+ if not group_dn :
151
+ self .logger .warning ("No group found for: %s" , group )
152
+ continue
153
+ group_member_subfilter = self .format_ldap_query_string (group_member_filter_format , group_dn = group_dn )
154
+ if not group_member_subfilter .startswith ('(' ):
155
+ group_member_subfilter = six .text_type ('(' ) + group_member_subfilter + six .text_type (')' )
156
+ user_subfilter = all_users_filter
157
+ if not user_subfilter .startswith ('(' ):
158
+ user_subfilter = six .text_type ('(' ) + user_subfilter + six .text_type (')' )
159
+ group_user_filter = six .text_type ('(&' ) + group_member_subfilter + user_subfilter + six .text_type (')' )
160
+ try :
161
+ for user_dn , user in self .iter_users (group_user_filter , extended_attributes ):
162
+ user ['groups' ].append (group )
163
+ group_users += 1
164
+ self .logger .debug ('Count of users in group "%s": %d' , group , group_users )
165
+ except Exception as e :
166
+ raise AssertionException ('Unexpected LDAP failure reading group members: %s' % e )
167
+ else :
168
+ members = self .find_ldap_group_member_dn (group , two_steps_group_member_attribute_name )
169
+ for member in members :
170
+ if member in all_users_records :
171
+ user = all_users_records [member ]
172
+ user ['groups' ].append (group )
173
+ group_users += 1
157
174
158
175
# if all users are requested, do an additional search for all of them
159
176
if all_users :
@@ -197,6 +214,33 @@ def find_ldap_group_dn(self, group):
197
214
group_dn = current_tuple [0 ]
198
215
return group_dn
199
216
217
+ def find_ldap_group_member_dn (self , group , member_attribute ):
218
+ """
219
+ :type group: str
220
+ :type member_attribute: str
221
+ :rtype list
222
+ """
223
+ connection = self .connection
224
+ options = self .options
225
+ base_dn = six .text_type (options ['base_dn' ])
226
+ group_filter_format = six .text_type (options ['group_filter_format' ])
227
+ try :
228
+ filter_string = self .format_ldap_query_string (group_filter_format , group = group )
229
+ res = connection .search_s (base_dn , ldap .SCOPE_SUBTREE ,
230
+ filterstr = filter_string , attrlist = [member_attribute ])
231
+ except Exception as e :
232
+ raise AssertionException ('Unexpected LDAP failure reading group info: %s' % e )
233
+ group_members = []
234
+ group_dn = None
235
+ for current_tuple in res :
236
+ if current_tuple [0 ]:
237
+ if group_dn :
238
+ raise AssertionException ("Multiple LDAP groups found for: %s" % group )
239
+ group_dn = current_tuple [0 ]
240
+ if member_attribute in current_tuple [1 ]:
241
+ group_members = current_tuple [1 ][member_attribute ]
242
+ return group_members
243
+
200
244
def iter_users (self , users_filter , extended_attributes ):
201
245
options = self .options
202
246
base_dn = six .text_type (options ['base_dn' ])
0 commit comments