1
1
#!/usr/bin/env python3
2
2
3
+ import re
3
4
import os
4
5
import sys
5
6
import json
6
7
import getopt
8
+ import subprocess
7
9
import collections
8
10
import urllib .error
9
11
import urllib .request
16
18
MAXTIMEOUT = 625
17
19
TIMEOUTMULTIPLE = 5
18
20
21
+ LDAP_AUTH_COMMAND = [
22
+ "awk" , "/ldap_default_authtok/ {print $3}" , "/etc/sssd/conf.d/0060_domain_CILOGON.ORG.conf" ,
23
+ ]
24
+
25
+ LDAP_GROUP_MEMBERS_COMMAND = [
26
+ "ldapsearch" ,
27
+ "-H" ,
28
+ "ldaps://ldap.cilogon.org" ,
29
+ "-D" ,
30
+ "uid=readonly_user,ou=system,o=OSG,o=CO,dc=cilogon,dc=org" ,
31
+ "-w" , "{}" ,
32
+ "-b" ,
33
+ "ou=groups,o=OSG,o=CO,dc=cilogon,dc=org" ,
34
+ "-s" ,
35
+ "one" ,
36
+ "(cn=*)" ,
37
+ ]
38
+
39
+ LDAP_ACTIVE_USERS_COMMAND = [
40
+ "ldapsearch" ,
41
+ "-LLL" ,
42
+ "-H" , "ldaps://ldap.cilogon.org" ,
43
+ "-D" , "uid=readonly_user,ou=system,o=OSG,o=CO,dc=cilogon,dc=org" ,
44
+ "-x" ,
45
+ "-w" , "{}" ,
46
+ "-b" , "ou=people,o=OSG,o=CO,dc=cilogon,dc=org" ,
47
+ "(isMemberOf=CO:members:active)" , "voPersonApplicationUID" ,
48
+ "|" , "grep" , "voPersonApplicationUID" ,
49
+ "|" , "sort" ,
50
+ ]
19
51
20
52
_usage = f"""\
21
53
usage: [PASS=...] { SCRIPT } [OPTIONS]
@@ -142,13 +174,19 @@ def get_osg_co_groups__map():
142
174
return { g ["Id" ]: g ["Name" ] for g in data }
143
175
144
176
145
- def co_group_is_ospool (gid ):
177
+ def co_group_is_project (gid ):
146
178
#print(f"co_group_is_ospool({gid})")
147
179
resp_data = get_co_group_identifiers (gid )
148
180
data = get_datalist (resp_data , "Identifiers" )
149
181
return any ( i ["Type" ] == "ospoolproject" for i in data )
150
182
151
183
184
+ def get_co_group_osggid (gid ):
185
+ resp_data = get_co_group_identifiers (gid )
186
+ data = get_datalist (resp_data , "Identifiers" )
187
+ return list (filter (lambda x : x ["Type" ] == "osggid" , data ))[0 ]["Identifier" ]
188
+
189
+
152
190
def get_co_group_members__pids (gid ):
153
191
#print(f"get_co_group_members__pids({gid})")
154
192
resp_data = get_co_group_members (gid )
@@ -192,6 +230,84 @@ def parse_options(args):
192
230
options .authstr = mkauthstr (user , passwd )
193
231
194
232
233
+ def get_ldap_group_members_data ():
234
+ gidNumber_str = "gidNumber: "
235
+ gidNumber_regex = re .compile (gidNumber_str )
236
+ member_str = f"hasMember: "
237
+ member_regex = re .compile (member_str )
238
+
239
+ auth_str = subprocess .run (
240
+ LDAP_AUTH_COMMAND ,
241
+ stdout = subprocess .PIPE
242
+ ).stdout .decode ('utf-8' ).strip ()
243
+
244
+ ldap_group_members_command = LDAP_GROUP_MEMBERS_COMMAND
245
+ ldap_group_members_command [LDAP_GROUP_MEMBERS_COMMAND .index ("{}" )] = auth_str
246
+
247
+ data_file = subprocess .run (
248
+ ldap_group_members_command , stdout = subprocess .PIPE ).stdout .decode ('utf-8' ).split ('\n ' )
249
+
250
+ search_results = list (filter (
251
+ lambda x : not re .compile ("#|dn|cn|objectClass" ).match (x ),
252
+ (line for line in data_file )))
253
+
254
+ search_results .reverse ()
255
+
256
+ group_data_dict = dict ()
257
+ index = 0
258
+ while index < len (search_results ) - 1 :
259
+ while not gidNumber_regex .match (search_results [index ]):
260
+ index += 1
261
+ gid = search_results [index ].replace (gidNumber_str , "" )
262
+ members_list = []
263
+ while search_results [index ] != "" :
264
+ if member_regex .match (search_results [index ]):
265
+ members_list .append (search_results [index ].replace (member_str , "" ))
266
+ index += 1
267
+ group_data_dict [gid ] = members_list
268
+ index += 1
269
+
270
+ return group_data_dict
271
+
272
+
273
+ def get_ldap_active_users ():
274
+ auth_str = subprocess .run (
275
+ LDAP_AUTH_COMMAND ,
276
+ stdout = subprocess .PIPE
277
+ ).stdout .decode ('utf-8' ).strip ()
278
+
279
+ ldap_active_users_command = LDAP_ACTIVE_USERS_COMMAND
280
+ ldap_active_users_command [LDAP_ACTIVE_USERS_COMMAND .index ("{}" )] = auth_str
281
+
282
+ active_users = subprocess .run (ldap_active_users_command , stdout = subprocess .PIPE ).stdout .decode ('utf-8' ).split ('\n ' )
283
+ users = set (line .replace ("voPersonApplicationUID: " , "" ) if re .compile ("dn: voPerson*" ) else "" for line in active_users )
284
+ return users
285
+
286
+
287
+ def create_user_to_projects_map (project_to_user_map , active_users , osggids_to_names ):
288
+ users_to_projects_map = dict ()
289
+ for osggid in project_to_user_map :
290
+ for user in project_to_user_map [osggid ]:
291
+ if user in active_users :
292
+ if user not in users_to_projects_map :
293
+ users_to_projects_map [user ] = [osggids_to_names [osggid ]]
294
+ else :
295
+ users_to_projects_map [user ].append (osggids_to_names [osggid ])
296
+
297
+ return users_to_projects_map
298
+
299
+
300
+ def get_co_api_data ():
301
+ #TODO add cacheing for COManage API data
302
+
303
+ groups = get_osg_co_groups__map ()
304
+ project_osggids_to_name = dict ()
305
+ for id ,name in groups .items ():
306
+ if co_group_is_project (id ):
307
+ project_osggids_to_name [get_co_group_osggid (id )] = name
308
+ return project_osggids_to_name
309
+
310
+
195
311
def gid_pids_to_osguser_pid_gids (gid_pids , pid_osguser ):
196
312
pid_gids = collections .defaultdict (set )
197
313
@@ -211,17 +327,29 @@ def filter_by_group(pid_gids, groups, filter_group_name):
211
327
212
328
213
329
def get_osguser_groups (filter_group_name = None ):
214
- groups = get_osg_co_groups__map ()
215
- ospool_gids = filter (co_group_is_ospool , groups )
216
- gid_pids = { gid : get_co_group_members__pids (gid ) for gid in ospool_gids }
217
- all_pids = set ( pid for gid in gid_pids for pid in gid_pids [gid ] )
218
- pid_osguser = { pid : get_co_person_osguser (pid ) for pid in all_pids }
219
- pid_gids = gid_pids_to_osguser_pid_gids (gid_pids , pid_osguser )
220
- if filter_group_name is not None :
221
- pid_gids = filter_by_group (pid_gids , groups , filter_group_name )
222
-
223
- return { pid_osguser [pid ]: sorted (map (groups .get , gids ))
224
- for pid , gids in pid_gids .items () }
330
+ project_osggids_to_name = get_co_api_data ()
331
+ ldap_groups_members = get_ldap_group_members_data ()
332
+ ldap_users = get_ldap_active_users ()
333
+
334
+ active_project_osggids = set (ldap_groups_members .keys ()).intersection (set (project_osggids_to_name .keys ()))
335
+ project_to_user_map = {
336
+ osggid : ldap_groups_members [osggid ]
337
+ for osggid in active_project_osggids
338
+ }
339
+ all_project_users = set (
340
+ username for osggid in project_to_user_map for username in project_to_user_map [osggid ]
341
+ )
342
+ all_active_project_users = all_project_users .intersection (ldap_users )
343
+ usernames_to_project_map = create_user_to_projects_map (
344
+ project_to_user_map ,
345
+ all_active_project_users ,
346
+ project_osggids_to_name ,
347
+ )
348
+
349
+ #if filter_group_name is not None:
350
+ #pid_gids = filter_by_group(pid_gids, groups, filter_group_name)
351
+
352
+ return usernames_to_project_map
225
353
226
354
227
355
def print_usermap_to_file (osguser_groups , file ):
0 commit comments