11#!/usr/bin/env python3
22
3+ import re
34import os
45import sys
56import json
67import getopt
8+ import subprocess
79import collections
810import urllib .error
911import urllib .request
1618MAXTIMEOUT = 625
1719TIMEOUTMULTIPLE = 5
1820
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+ ]
1951
2052_usage = f"""\
2153 usage: [PASS=...] { SCRIPT } [OPTIONS]
@@ -142,13 +174,19 @@ def get_osg_co_groups__map():
142174 return { g ["Id" ]: g ["Name" ] for g in data }
143175
144176
145- def co_group_is_ospool (gid ):
177+ def co_group_is_project (gid ):
146178 #print(f"co_group_is_ospool({gid})")
147179 resp_data = get_co_group_identifiers (gid )
148180 data = get_datalist (resp_data , "Identifiers" )
149181 return any ( i ["Type" ] == "ospoolproject" for i in data )
150182
151183
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+
152190def get_co_group_members__pids (gid ):
153191 #print(f"get_co_group_members__pids({gid})")
154192 resp_data = get_co_group_members (gid )
@@ -192,6 +230,84 @@ def parse_options(args):
192230 options .authstr = mkauthstr (user , passwd )
193231
194232
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+
195311def gid_pids_to_osguser_pid_gids (gid_pids , pid_osguser ):
196312 pid_gids = collections .defaultdict (set )
197313
@@ -211,17 +327,29 @@ def filter_by_group(pid_gids, groups, filter_group_name):
211327
212328
213329def 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
225353
226354
227355def print_usermap_to_file (osguser_groups , file ):
0 commit comments