Skip to content

Commit a4d6477

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 30227b1 commit a4d6477

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,8 +1,10 @@
11
#!/usr/bin/env python3
22

3+
import re
34
import os
45
import sys
56
import getopt
7+
import subprocess
68
import collections
79
import urllib.error
810
import urllib.request
@@ -13,6 +15,36 @@
1315
ENDPOINT = "https://registry-test.cilogon.org/registry/"
1416
OSG_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+
74112
def 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+
118234
def 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

136252
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
148276

149277

150278
def print_usermap_to_file(osguser_groups, file):

0 commit comments

Comments
 (0)