#!/usr/bin/python3 """ Find all groups for which this user or group has admin, read, or update privileges which are revokable (direct privileges). Example: grouper_find_privileges.py -m dev -u abc1234 """ import argparse import requests from requests.auth import HTTPBasicAuth import json import sys,string def grouperGroupsWithThisSubjectPriv(grouper_credentials, grouper_ws_uri, subject_id, privName): """Get the list of groups with this subject,privilege assigned""" body = { "WsRestGetGrouperPrivilegesLiteRequest": { "subjectId": subject_id, "privilegeName": privName, "privilegeType": "access", } } return grouperWSRequest(grouper_credentials, grouper_ws_uri+"/grouperPrivileges", "POST", body) def grouperGetUuid(grouper_credentials, grouper_ws_uri, groupName): """Get UUID for the specified group""" thisuuid = 0 body = { "WsRestFindGroupsRequest": { "wsQueryFilter": { "groupName": groupName, "queryFilterType": "FIND_BY_GROUP_NAME_EXACT", } } } findGroups = grouperWSRequest(grouper_credentials, grouper_ws_uri+"/groups", "POST", body) if findGroups and findGroups['WsFindGroupsResults']['resultMetadata']['success'] and 'groupResults' in findGroups['WsFindGroupsResults']: thisuuid = findGroups['WsFindGroupsResults']['groupResults'][0]['uuid'] return thisuuid def grouperWSRequest(grouper_credentials, url, method, body=None): """Send a request to the Grouper Web Service.""" try: response = requests.request(method, url, json=body, auth=grouper_credentials) response.raise_for_status() except requests.RequestException as e: raise SystemExit(e) from None return response.json() def find_privileges(mode, subject): """Get the list of groups for which this subject has admin,read,update privilege Args: mode (str): The environment mode ('dev', 'prod'). subject (str): The subject can be a UNI, UUID, or group ID path. """ # set the Grouper Web Service username and password grouper_username = 'abc1234' grouper_password = 'xxxxxxxxxxxxxxxxxxxx' grouper_credentials = HTTPBasicAuth(grouper_username,grouper_password) # the Grouper Web Service URI should point to dev or prod Grouper devGrouperURI = 'https://grouper-dev.cc.columbia.edu/grouper-ws/servicesRest/v2_4_000' prodGrouperURI = 'https://grouper.cc.columbia.edu/grouper-ws/servicesRest/v2_4_000' if mode == 'prod': grouper_ws_uri = prodGrouperURI else: grouper_ws_uri = devGrouperURI # If subject is a group ID path, get the UUID this_subject = subject if ":" in subject: subject_uuid = grouperGetUuid(grouper_credentials,grouper_ws_uri,subject) if subject_uuid == 0: print(f"{subject} group not found (does not exist or is not accessible)") return this_subject = subject_uuid for this_privilege in ["ADMIN", "READ", "UPDATE"]: # Find the group members result = grouperGroupsWithThisSubjectPriv(grouper_credentials,grouper_ws_uri,this_subject,this_privilege) if ( not result or not result['WsGetGrouperPrivilegesLiteResult']['resultMetadata']['success'] ): print(f"Unable to get {this_privilege} groups for {subject}") continue if "privilegeResults" not in result["WsGetGrouperPrivilegesLiteResult"]: # none found continue triplets = result["WsGetGrouperPrivilegesLiteResult"]["privilegeResults"] for ntriplets in range(0, len(triplets)): this_group = triplets[ntriplets]["wsGroup"] # this_subject = triplets[ntriplets]["wsSubject"] # priv_name = triplets[ntriplets]["privilegeName"] revokable = triplets[ntriplets]["revokable"] group_name = this_group["name"] # source_id = this_subject["sourceId"] # subject_id = this_subject["id"] if revokable == "T": print(f"{this_privilege},{group_name}") def main(): """Parses command-line arguments and calls find_privileges.""" parser = argparse.ArgumentParser( description=("Find all groups for which this person or group has " + "admin, read, update privileges which are revokable " + "(direct privileges)."), ) parser.add_argument( "-m", action="store", dest="mode", required=True, choices=["dev", "prod"], type=str.lower, help="the Grouper environment mode", ) parser.add_argument( "-u", action="store", dest="subject", required=True, help="the subject can be a UNI, UUID, or group ID path", ) args = parser.parse_args() find_privileges(args.mode, args.subject) if __name__ == "__main__": main()