11#!/usr/bin/env python3
22
3+ import re
34import os
45import sys
56import getopt
7+ import subprocess
68import collections
79import urllib .error
810import urllib .request
1315ENDPOINT = "https://registry-test.cilogon.org/registry/"
1416OSG_CO_ID = 8
1517
18+ LDAP_AUTH_COMMAND = [
19+ "awk" , "/ldap_default_authtok/ {print $3}" , "/etc/sssd/conf.d/0060_domain_CILOGON.ORG.conf" ,
20+ ]
21+
22+ LDAP_GROUP_MEMBERS_COMMAND = [
23+ "ldapsearch" ,
24+ "-H" ,
25+ "ldaps://ldap.cilogon.org" ,
26+ "-D" ,
27+ "uid=readonly_user,ou=system,o=OSG,o=CO,dc=cilogon,dc=org" ,
28+ "-w" , "{}" ,
29+ "-b" ,
30+ "ou=groups,o=OSG,o=CO,dc=cilogon,dc=org" ,
31+ "-s" ,
32+ "one" ,
33+ "(cn=*)" ,
34+ ]
35+
36+ LDAP_ACTIVE_USERS_COMMAND = [
37+ "ldapsearch" ,
38+ "-LLL" ,
39+ "-H" , "ldaps://ldap.cilogon.org" ,
40+ "-D" , "uid=readonly_user,ou=system,o=OSG,o=CO,dc=cilogon,dc=org" ,
41+ "-x" ,
42+ "-w" , "{}" ,
43+ "-b" , "ou=people,o=OSG,o=CO,dc=cilogon,dc=org" ,
44+ "(isMemberOf=CO:members:active)" , "voPersonApplicationUID" ,
45+ "|" , "grep" , "voPersonApplicationUID" ,
46+ "|" , "sort" ,
47+ ]
1648
1749_usage = f"""\
1850 usage: [PASS=...] { SCRIPT } [OPTIONS]
@@ -64,13 +96,19 @@ def get_osg_co_groups__map():
6496 return { g ["Id" ]: g ["Name" ] for g in data }
6597
6698
67- def co_group_is_ospool (gid ):
99+ def co_group_is_project (gid ):
68100 #print(f"co_group_is_ospool({gid})")
69101 resp_data = utils .get_co_group_identifiers (gid , options .endpoint , options .authstr )
70102 data = utils .get_datalist (resp_data , "Identifiers" )
71103 return any ( i ["Type" ] == "ospoolproject" for i in data )
72104
73105
106+ def get_co_group_osggid (gid ):
107+ resp_data = get_co_group_identifiers (gid )
108+ data = get_datalist (resp_data , "Identifiers" )
109+ return list (filter (lambda x : x ["Type" ] == "osggid" , data ))[0 ]["Identifier" ]
110+
111+
74112def get_co_group_members__pids (gid ):
75113 #print(f"get_co_group_members__pids({gid})")
76114 resp_data = utils .get_co_group_members (gid , options .endpoint , options .authstr )
@@ -115,6 +153,84 @@ def parse_options(args):
115153 usage ("PASS required" )
116154
117155
156+ def get_ldap_group_members_data ():
157+ gidNumber_str = "gidNumber: "
158+ gidNumber_regex = re .compile (gidNumber_str )
159+ member_str = f"hasMember: "
160+ member_regex = re .compile (member_str )
161+
162+ auth_str = subprocess .run (
163+ LDAP_AUTH_COMMAND ,
164+ stdout = subprocess .PIPE
165+ ).stdout .decode ('utf-8' ).strip ()
166+
167+ ldap_group_members_command = LDAP_GROUP_MEMBERS_COMMAND
168+ ldap_group_members_command [LDAP_GROUP_MEMBERS_COMMAND .index ("{}" )] = auth_str
169+
170+ data_file = subprocess .run (
171+ ldap_group_members_command , stdout = subprocess .PIPE ).stdout .decode ('utf-8' ).split ('\n ' )
172+
173+ search_results = list (filter (
174+ lambda x : not re .compile ("#|dn|cn|objectClass" ).match (x ),
175+ (line for line in data_file )))
176+
177+ search_results .reverse ()
178+
179+ group_data_dict = dict ()
180+ index = 0
181+ while index < len (search_results ) - 1 :
182+ while not gidNumber_regex .match (search_results [index ]):
183+ index += 1
184+ gid = search_results [index ].replace (gidNumber_str , "" )
185+ members_list = []
186+ while search_results [index ] != "" :
187+ if member_regex .match (search_results [index ]):
188+ members_list .append (search_results [index ].replace (member_str , "" ))
189+ index += 1
190+ group_data_dict [gid ] = members_list
191+ index += 1
192+
193+ return group_data_dict
194+
195+
196+ def get_ldap_active_users ():
197+ auth_str = subprocess .run (
198+ LDAP_AUTH_COMMAND ,
199+ stdout = subprocess .PIPE
200+ ).stdout .decode ('utf-8' ).strip ()
201+
202+ ldap_active_users_command = LDAP_ACTIVE_USERS_COMMAND
203+ ldap_active_users_command [LDAP_ACTIVE_USERS_COMMAND .index ("{}" )] = auth_str
204+
205+ active_users = subprocess .run (ldap_active_users_command , stdout = subprocess .PIPE ).stdout .decode ('utf-8' ).split ('\n ' )
206+ users = set (line .replace ("voPersonApplicationUID: " , "" ) if re .compile ("dn: voPerson*" ) else "" for line in active_users )
207+ return users
208+
209+
210+ def create_user_to_projects_map (project_to_user_map , active_users , osggids_to_names ):
211+ users_to_projects_map = dict ()
212+ for osggid in project_to_user_map :
213+ for user in project_to_user_map [osggid ]:
214+ if user in active_users :
215+ if user not in users_to_projects_map :
216+ users_to_projects_map [user ] = [osggids_to_names [osggid ]]
217+ else :
218+ users_to_projects_map [user ].append (osggids_to_names [osggid ])
219+
220+ return users_to_projects_map
221+
222+
223+ def get_co_api_data ():
224+ #TODO add cacheing for COManage API data
225+
226+ groups = get_osg_co_groups__map ()
227+ project_osggids_to_name = dict ()
228+ for id ,name in groups .items ():
229+ if co_group_is_project (id ):
230+ project_osggids_to_name [get_co_group_osggid (id )] = name
231+ return project_osggids_to_name
232+
233+
118234def gid_pids_to_osguser_pid_gids (gid_pids , pid_osguser ):
119235 pid_gids = collections .defaultdict (set )
120236
@@ -134,17 +250,29 @@ def filter_by_group(pid_gids, groups, filter_group_name):
134250
135251
136252def get_osguser_groups (filter_group_name = None ):
137- groups = get_osg_co_groups__map ()
138- ospool_gids = filter (co_group_is_ospool , groups )
139- gid_pids = { gid : get_co_group_members__pids (gid ) for gid in ospool_gids }
140- all_pids = set ( pid for gid in gid_pids for pid in gid_pids [gid ] )
141- pid_osguser = { pid : get_co_person_osguser (pid ) for pid in all_pids }
142- pid_gids = gid_pids_to_osguser_pid_gids (gid_pids , pid_osguser )
143- if filter_group_name is not None :
144- pid_gids = filter_by_group (pid_gids , groups , filter_group_name )
145-
146- return { pid_osguser [pid ]: sorted (map (groups .get , gids ))
147- for pid , gids in pid_gids .items () }
253+ project_osggids_to_name = get_co_api_data ()
254+ ldap_groups_members = get_ldap_group_members_data ()
255+ ldap_users = get_ldap_active_users ()
256+
257+ active_project_osggids = set (ldap_groups_members .keys ()).intersection (set (project_osggids_to_name .keys ()))
258+ project_to_user_map = {
259+ osggid : ldap_groups_members [osggid ]
260+ for osggid in active_project_osggids
261+ }
262+ all_project_users = set (
263+ username for osggid in project_to_user_map for username in project_to_user_map [osggid ]
264+ )
265+ all_active_project_users = all_project_users .intersection (ldap_users )
266+ usernames_to_project_map = create_user_to_projects_map (
267+ project_to_user_map ,
268+ all_active_project_users ,
269+ project_osggids_to_name ,
270+ )
271+
272+ #if filter_group_name is not None:
273+ #pid_gids = filter_by_group(pid_gids, groups, filter_group_name)
274+
275+ return usernames_to_project_map
148276
149277
150278def print_usermap_to_file (osguser_groups , file ):
0 commit comments