1
1
#!/usr/bin/env python3
2
2
3
+ import re
3
4
import os
4
5
import sys
5
6
import getopt
7
+ import subprocess
6
8
import collections
7
9
import urllib .error
8
10
import urllib .request
13
15
ENDPOINT = "https://registry-test.cilogon.org/registry/"
14
16
OSG_CO_ID = 8
15
17
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
+ ]
16
48
17
49
_usage = f"""\
18
50
usage: [PASS=...] { SCRIPT } [OPTIONS]
@@ -64,13 +96,19 @@ def get_osg_co_groups__map():
64
96
return { g ["Id" ]: g ["Name" ] for g in data }
65
97
66
98
67
- def co_group_is_ospool (gid ):
99
+ def co_group_is_project (gid ):
68
100
#print(f"co_group_is_ospool({gid})")
69
101
resp_data = utils .get_co_group_identifiers (gid , options .endpoint , options .authstr )
70
102
data = utils .get_datalist (resp_data , "Identifiers" )
71
103
return any ( i ["Type" ] == "ospoolproject" for i in data )
72
104
73
105
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
+
74
112
def get_co_group_members__pids (gid ):
75
113
#print(f"get_co_group_members__pids({gid})")
76
114
resp_data = utils .get_co_group_members (gid , options .endpoint , options .authstr )
@@ -115,6 +153,84 @@ def parse_options(args):
115
153
usage ("PASS required" )
116
154
117
155
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
+
118
234
def gid_pids_to_osguser_pid_gids (gid_pids , pid_osguser ):
119
235
pid_gids = collections .defaultdict (set )
120
236
@@ -134,17 +250,29 @@ def filter_by_group(pid_gids, groups, filter_group_name):
134
250
135
251
136
252
def 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
148
276
149
277
150
278
def print_usermap_to_file (osguser_groups , file ):
0 commit comments