| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. See accompanying LICENSE file. | |
| # | |
| import argparse | |
| import os,sys | |
| import getpass | |
| import logging | |
| import time | |
| import requests | |
| s = requests.Session() | |
| def log(msg,type): | |
| if type == 'info': | |
| logging.info(" %s",msg) | |
| if type == 'debug': | |
| logging.debug(" %s",msg) | |
| if type == 'warning': | |
| logging.warning(" %s",msg) | |
| if type == 'exception': | |
| logging.exception(" %s",msg) | |
| if type == 'error': | |
| logging.error(" %s",msg) | |
| def isPairedSwitch(value): | |
| isSwitch=False | |
| switch_arr =["-groups", "-users","-admin","-url","-sslCertPath"] | |
| if value in switch_arr: | |
| isSwitch=True | |
| return isSwitch | |
| def printUsage(): | |
| log("[I] Note : This utility can be used to delete users or groups, To delete groups refer below given first command and to delete users refer second command.","info") | |
| log("[I] Usage(Group delete): deleteUserGroupUtil.py -groups <group file path> -admin <ranger admin user> -url <rangerhosturl> [-force] [-sslCertPath <cert path>] [-debug]","info") | |
| log("[I] Usage(User delete): deleteUserGroupUtil.py -users <user file path> -admin <ranger admin user> -url <rangerhosturl> [-force] [-sslCertPath <cert path>] [-debug]","info") | |
| log("[I] -groups: Delete groups specified in the given file","info") | |
| log("[I] -users: Delete users specified in the given file","info") | |
| log("[I] -admin: Ranger Admin user ID","info") | |
| log("[I] -force: Force delete users/groups, even if they are referenced in policies","info") | |
| log("[I] -url: Ranger Admin URL","info") | |
| log("[I] -sslCertPath: Filepath to ssl certificate to use when Ranger Admin uses HTTPS","info") | |
| log("[I] -debug: Enables debugging","info") | |
| sys.exit(1) | |
| def processRequest(url, username, password, data, method, isHttps, certfile, isDebug): | |
| verify = isHttps | |
| if isHttps: | |
| verify = certfile | |
| if method.lower() == 'get': | |
| response = s.get(url, data=data, auth=(username, password),verify=verify) | |
| elif method.lower() == 'delete': | |
| response = s.delete(url, data=data, auth=(username, password),verify=verify) | |
| else: | |
| log("[E] Unsupported method"+method,'error') | |
| pass | |
| #log("[I] Request time: %s seconds" % str(response.elapsed.total_seconds()),"info") | |
| response_code = response.status_code | |
| if isDebug ==True or (response_code!=200 and response_code!=204): | |
| log('Request URL = ' + str(url),'debug') | |
| log('Response = ' + str(response.headers),'debug') | |
| return response_code | |
| def validateArgs(argv): | |
| if(len(argv)<7): | |
| log("[E] insufficient number of arguments. Found " + str(len(argv)) + "; expected at least 7","error") | |
| printUsage() | |
| if not "-users" in argv and not "-groups" in argv: | |
| log("[E] -users or -groups switch was missing!","error") | |
| printUsage() | |
| if not "-admin" in argv: | |
| log("[E] -admin switch was missing!","error") | |
| printUsage() | |
| if not "-url" in argv: | |
| log("[E] -url switch was missing!","error") | |
| printUsage() | |
| if "-url" in argv: | |
| try: | |
| host=str(argv[argv.index("-url")+1]) | |
| host=host.strip() | |
| if host =="" or host is None or isPairedSwitch(host): | |
| log("[E] invalid Ranger Admin host URL","error") | |
| printUsage() | |
| if host.lower().startswith("https"): | |
| if not "-sslCertPath" in argv: | |
| log("[E] -sslCertPath switch was missing!","error") | |
| printUsage() | |
| except IndexError: | |
| log("[E] missing/invalid Ranger Admin host URL","error") | |
| printUsage() | |
| def main(argv): | |
| start_time = time.time() | |
| FORMAT = '%(asctime)-15s %(message)s' | |
| logging.basicConfig(format=FORMAT, level=logging.DEBUG) | |
| inputPath="" | |
| certfile="" | |
| tail="" | |
| password="" | |
| isHttps=False | |
| isUser=False | |
| isGroup=False | |
| isDebug=False | |
| if "-usage" in argv or "-help" in argv: | |
| printUsage() | |
| validateArgs(argv) | |
| for i in range(1, len(argv)) : | |
| if str(argv[i])== "-groups" : | |
| restpath= "/groups/groupName/" | |
| try: | |
| inputPath=str(argv[i+1]) | |
| inputPath=inputPath.strip() | |
| if inputPath =="" or not os.path.exists(inputPath) or not os.path.isfile(inputPath) or not os.access(inputPath, os.R_OK) or isPairedSwitch(inputPath): | |
| log("[E] File '"+inputPath+"' does not exist or could not be read","error") | |
| sys.exit(1) | |
| else: | |
| isGroup=True | |
| if os.stat(inputPath).st_size == 0: | |
| log("[E] File '"+inputPath+"' is empty!","error") | |
| sys.exit(1) | |
| except IndexError: | |
| log("[E] missing filename after '-groups' argument","error") | |
| sys.exit(1) | |
| continue | |
| elif str(argv[i])== "-users" : | |
| restpath= "/users/userName/" | |
| try: | |
| inputPath=str(argv[i+1]) | |
| inputPath=inputPath.strip() | |
| if inputPath =="" or not os.path.exists(inputPath) or not os.path.isfile(inputPath) or not os.access(inputPath, os.R_OK) or isPairedSwitch(inputPath): | |
| log("[E] File '"+inputPath+"' does not exist or could not be read","error") | |
| sys.exit(1) | |
| else: | |
| isUser=True | |
| if os.stat(inputPath).st_size == 0: | |
| log("[E] File '"+inputPath+"' is empty!","error") | |
| sys.exit(1) | |
| except IndexError: | |
| log("[E] missing filename after '-users' argument","error") | |
| sys.exit(1) | |
| continue | |
| if str(argv[i])=="-admin" : | |
| try: | |
| user=str(argv[i+1]) | |
| if user =="" or user is None or isPairedSwitch(user): | |
| log("[E] missing/invalid Ranger Admin login ID for argument '-admin'","error") | |
| sys.exit(1) | |
| continue | |
| except IndexError: | |
| log("[E] missing/invalid Ranger Admin login ID for argument '-admin'","error") | |
| sys.exit(1) | |
| if str(argv[i])=="-url" : | |
| try: | |
| host=str(argv[i+1]) | |
| host=host.strip() | |
| if host =="" or host is None or isPairedSwitch(host): | |
| log("[E] invalid Ranger Admin host URL","error") | |
| sys.exit(1) | |
| if host.lower().startswith("https"): | |
| isHttps=True | |
| continue | |
| except IndexError: | |
| log("[E] missing/invalid Ranger Admin host URL","error") | |
| sys.exit(1) | |
| if str(argv[i])=="-force" : | |
| tail="?forceDelete=true" | |
| continue | |
| if str(argv[i])=="-debug" : | |
| isDebug=True | |
| continue | |
| if isHttps == True and str(argv[i])== "-sslCertPath" : | |
| try: | |
| certfile=str(argv[i+1]) | |
| certfile=certfile.strip() | |
| if certfile =="" or not os.path.exists(certfile) or not os.path.isfile(certfile) or not os.access(certfile, os.R_OK) or isPairedSwitch(certfile): | |
| log("[E] Certificate File '"+certfile+"' does not exist or could not be read","error") | |
| sys.exit(1) | |
| except IndexError: | |
| log("[E] missing/invalid SSL certificate path for argument '-sslCertPath'","error") | |
| sys.exit(1) | |
| continue | |
| if isUser==True and isGroup==True: | |
| log("[E] -users and -groups both option were provided, only one is allowed.","error") | |
| printUsage() | |
| io_time = 0 | |
| if password =="" : | |
| io_start_time = time.time() | |
| password=getpass.getpass("Enter Ranger Admin password : ") | |
| io_end_time = time.time() | |
| io_time = io_end_time - io_start_time | |
| url=host+'/service/xusers/secure/users/roles/userName/'+user | |
| response_code=0 | |
| try: | |
| response_code=processRequest(url,user,password,None,'get',isHttps,certfile,False) | |
| except Exception as e: | |
| log("[E] request error: %s:" % (e), "error") | |
| sys.exit(1) | |
| if response_code == 302 or response_code==401 or response_code==403: | |
| log("[E] Authentication Error:Please try with valid credentials!","error") | |
| sys.exit(1) | |
| if response_code != 200: | |
| log("[E] Failed to contact Ranger Admin with given parameters. Please review the parameters","error") | |
| printUsage() | |
| sys.exit(1) | |
| f=open(inputPath,'r') | |
| processedRows=0 | |
| for line in f: | |
| line=line.strip() | |
| if line == "" or line is None: | |
| continue | |
| if isUser==True and line==user: | |
| log("[I] Skipping deletion of user : "+line+", Self account deletion is restricted!","info") | |
| continue | |
| url=host+'/service/xusers'+restpath+line+tail | |
| method='delete' | |
| data=None | |
| response_code=processRequest(url,user,password,data,method,isHttps,certfile,isDebug) | |
| if response_code==302 or response_code==401: | |
| if isUser==True: | |
| log("[E] failed while deleting user '" + line + "'. Please verify the parameters","error") | |
| elif isGroup==True: | |
| log("[E] failed while deleting group '" + line + "'. Please verify the parameters","error") | |
| break | |
| elif response_code==204: | |
| if isUser==True: | |
| log("[I] Deleted user : "+line,"info") | |
| elif isGroup==True: | |
| log("[I] Deleted group : "+line,"info") | |
| processedRows=processedRows+1 | |
| elif response_code==404: | |
| if isUser==True: | |
| log("[E] failed while deleting user '" + line + "'. Please verify the parameters","error") | |
| elif isGroup==True: | |
| log("[E] failed while deleting group '" + line + "'. Please verify the parameters","error") | |
| elif response_code==400: | |
| if isUser==True: | |
| log("[I] User not found : "+line,"info") | |
| elif isGroup==True: | |
| log("[I] Group not found : "+line,"info") | |
| f.close() | |
| if processedRows==0: | |
| if isUser==True: | |
| log("[I] No valid user found to delete!","info") | |
| elif isGroup==True: | |
| log("[I] No valid group found to delete!","info") | |
| else: | |
| if isUser==True: | |
| log("[I] Number of user deleted : "+str(processedRows),"info") | |
| elif isGroup==True: | |
| log("[I] Number of group deleted : "+str(processedRows),"info") | |
| end_time = time.time() | |
| log("[I] Total time for io : "+str(io_time),"info") | |
| log("[I] Total time taken for execution : "+str(end_time-start_time)+" seconds","info") | |
| log("[I] Averge time taken for execution : "+str(float(end_time-start_time)/float(processedRows))+" seconds","info") | |
| log("[I] Total time taken for deletion : "+str(end_time-start_time-io_time)+" seconds","info") | |
| log("[I] Averge time taken for deletion : "+str(float(end_time-start_time-io_time)/float(processedRows))+" seconds","info") | |
| main(sys.argv) |