Skip to content

Commit 898f83b

Browse files
Initial Commit for the new project-usermap script
Uses LDAP search to find active and provisioned groups then compares them to the list project groups in COmanage to determine which LDAP groups and users to build the map out of.
1 parent c4262b9 commit 898f83b

File tree

1 file changed

+140
-12
lines changed

1 file changed

+140
-12
lines changed

osg-comanage-project-usermap.py

Lines changed: 140 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#!/usr/bin/env python3
22

3+
import re
34
import os
45
import sys
56
import json
67
import getopt
8+
import subprocess
79
import collections
810
import urllib.error
911
import urllib.request
@@ -16,6 +18,36 @@
1618
MAXTIMEOUT = 625
1719
TIMEOUTMULTIPLE = 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+
152190
def 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+
195311
def 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

213329
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
225353

226354

227355
def print_usermap_to_file(osguser_groups, file):

0 commit comments

Comments
 (0)