Repository: incubator-ranger Updated Branches: refs/heads/master d36a04a84 -> 3abd4be25
RANGER-806 : Ranger utility to delete users from Ranger Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/3abd4be2 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/3abd4be2 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/3abd4be2 Branch: refs/heads/master Commit: 3abd4be2555dc135067245a70d002920f1e9cb39 Parents: d36a04a Author: Pradeep Agrawal <[email protected]> Authored: Wed Mar 16 12:13:17 2016 +0530 Committer: Gautam Borad <[email protected]> Committed: Wed Mar 16 17:49:16 2016 +0530 ---------------------------------------------------------------------- security-admin/scripts/deleteUserGroupUtil.py | 279 +++++++++++++++++++ .../java/org/apache/ranger/biz/XUserMgr.java | 28 +- .../org/apache/ranger/common/db/BaseDao.java | 4 +- .../apache/ranger/db/XXGroupPermissionDao.java | 4 +- .../resources/META-INF/jpa_named_queries.xml | 2 +- .../org/apache/ranger/biz/TestXUserMgr.java | 5 + src/main/assembly/admin-web.xml | 1 + 7 files changed, 313 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/3abd4be2/security-admin/scripts/deleteUserGroupUtil.py ---------------------------------------------------------------------- diff --git a/security-admin/scripts/deleteUserGroupUtil.py b/security-admin/scripts/deleteUserGroupUtil.py new file mode 100644 index 0000000..04648b3 --- /dev/null +++ b/security-admin/scripts/deleteUserGroupUtil.py @@ -0,0 +1,279 @@ +# +# 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 pycurl +import getpass +import logging +from StringIO import StringIO as BytesIO +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,usernamepassword,data,method,isHttps,certfile,isDebug): + buffer = BytesIO() + header = BytesIO() + c = pycurl.Curl() + c.setopt(c.URL, url) + c.setopt(pycurl.HTTPHEADER, ['Content-Type: application/json','Accept: application/json']) + c.setopt(pycurl.USERPWD, usernamepassword) + c.setopt(pycurl.VERBOSE, 0) + if isHttps==True: + c.setopt(pycurl.SSL_VERIFYPEER,1) + c.setopt(pycurl.SSL_VERIFYHOST,2) + c.setopt(pycurl.CAINFO, certfile) + + c.setopt(c.WRITEFUNCTION ,buffer.write) + c.setopt(c.HEADERFUNCTION,header.write) + # setting proper method and parameters + if method == 'get' : + c.setopt(pycurl.HTTPGET, 1) + elif method == 'delete' : + c.setopt(pycurl.CUSTOMREQUEST, "DELETE") + c.setopt(c.POSTFIELDS, str(data)) + else : + log("[E] Unknown Http Request method found, only get or delete method are allowed!","error") + + c.perform() + # getting response + response = buffer.getvalue() + headerResponse = header.getvalue() + response_code=0 + response_code=str(c.getinfo(pycurl.RESPONSE_CODE)) + response_code=int(response_code) + buffer.close() + header.close() + c.close() + if isDebug ==True or (response_code!=200 and response_code!=204): + print 'Request URL = ' + str(url) + print 'Response = ' + str(headerResponse) + return response_code +def validateArgs(argv): + if(len(argv)<7): + log("[E] insufficient number of arguments. Found " + 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): + 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() + if password =="" : + password=getpass.getpass("Enter Ranger Admin password : ") + + usernamepassword=user+":"+password + url=host+'/service/xusers/secure/users/roles/userName/'+user + response_code=0 + try: + response_code=processRequest(url,usernamepassword,None,'get',isHttps,certfile,False) + except pycurl.error, e: + print e + 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,usernamepassword,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") + buffer.close() + header.close() + 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") +main(sys.argv) http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/3abd4be2/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java b/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java index d38da7d..5aed040 100644 --- a/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java @@ -57,6 +57,7 @@ import org.apache.ranger.db.XXAuditMapDao; import org.apache.ranger.db.XXAuthSessionDao; import org.apache.ranger.db.XXGroupDao; import org.apache.ranger.db.XXGroupGroupDao; +import org.apache.ranger.db.XXGroupPermissionDao; import org.apache.ranger.db.XXGroupUserDao; import org.apache.ranger.db.XXPermMapDao; import org.apache.ranger.db.XXPolicyDao; @@ -1447,6 +1448,9 @@ public class XUserMgr extends XUserMgrBase { searchCriteria.addParam("groupId", id); VXAuditMapList vXAuditMapList = searchXAuditMaps(searchCriteria); + XXGroupPermissionDao xXGroupPermissionDao=daoManager.getXXGroupPermission(); + List<XXGroupPermission> xXGroupPermissions=xXGroupPermissionDao.findByGroupId(id); + XXGroupGroupDao xXGroupGroupDao = daoManager.getXXGroupGroup(); List<XXGroupGroup> xXGroupGroups = xXGroupGroupDao.findByGroupId(id); @@ -1525,6 +1529,17 @@ public class XUserMgr extends XUserMgrBase { restErrorUtil.createRESTException(excp.getMessage()); } } + if(CollectionUtils.isNotEmpty(xXGroupPermissions)){ + for (XXGroupPermission xXGroupPermission : xXGroupPermissions) { + if(xXGroupPermission!=null){ + XXModuleDef xXModuleDef=daoManager.getXXModuleDef().findByModuleId(xXGroupPermission.getModuleId()); + if(xXModuleDef!=null){ + logger.warn("Deleting '" + xXModuleDef.getModule() + "' module permission for group '" + xXGroup.getName() + "'"); + } + xXGroupPermissionDao.remove(xXGroupPermission.getId()); + } + } + } //delete XXGroup xXGroupDao.remove(id); //Create XXTrxLog @@ -1534,19 +1549,22 @@ public class XUserMgr extends XUserMgrBase { } else { boolean hasReferences=false; - if(vxGroupUserList!=null && vxGroupUserList.getListSize()>0){ + if(vxGroupUserList.getListSize()>0){ hasReferences=true; } - if(hasReferences==false && xXPolicyList!=null && xXPolicyList.size()>0){ + if(hasReferences==false && CollectionUtils.isNotEmpty(xXPolicyList)){ hasReferences=true; } - if(hasReferences==false && vXPermMapList!=null && vXPermMapList.getListSize()>0){ + if(hasReferences==false && vXPermMapList.getListSize()>0){ hasReferences=true; } - if(hasReferences==false && vXAuditMapList!=null && vXAuditMapList.getListSize()>0){ + if(hasReferences==false && vXAuditMapList.getListSize()>0){ + hasReferences=true; + } + if(hasReferences==false && CollectionUtils.isNotEmpty(xXGroupGroups)){ hasReferences=true; } - if(hasReferences==false && xXGroupGroups!=null && xXGroupGroups.size()>0){ + if(hasReferences==false && CollectionUtils.isNotEmpty(xXGroupPermissions)){ hasReferences=true; } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/3abd4be2/security-admin/src/main/java/org/apache/ranger/common/db/BaseDao.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/common/db/BaseDao.java b/security-admin/src/main/java/org/apache/ranger/common/db/BaseDao.java index 665d85c..c25b989 100644 --- a/security-admin/src/main/java/org/apache/ranger/common/db/BaseDao.java +++ b/security-admin/src/main/java/org/apache/ranger/common/db/BaseDao.java @@ -258,8 +258,8 @@ public abstract class BaseDao<T> { logger.warn("Required annotation `Table` not found"); } String tableName = table.name(); - String query = "update " + tableName + " set " + tableName + "."+paramName+"=null" - + " where " + tableName + "."+paramName+"=" + oldID; + String query = "update " + tableName + " set " + paramName+"=null" + + " where " +paramName+"=" + oldID; int count=getEntityManager().createNativeQuery(query).executeUpdate(); if(count>0){ logger.warn(count + " records updated in table '" + tableName + "' with: set " + paramName + "=null where " + paramName + "=" + oldID); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/3abd4be2/security-admin/src/main/java/org/apache/ranger/db/XXGroupPermissionDao.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGroupPermissionDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGroupPermissionDao.java index 18ca9e3..f6444f8 100644 --- a/security-admin/src/main/java/org/apache/ranger/db/XXGroupPermissionDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXGroupPermissionDao.java @@ -63,12 +63,12 @@ public class XXGroupPermissionDao extends BaseDao<XXGroupPermission> { return null; } - public List<XXGroupPermission> findByGroupPermissionId(Long groupId) { + public List<XXGroupPermission> findByGroupId(Long groupId) { if (groupId != null) { try { return getEntityManager() .createNamedQuery( - "XXGroupPermission.findByGroupPermissionId", + "XXGroupPermission.findByGroupId", XXGroupPermission.class) .setParameter("groupId", groupId).getResultList(); } catch (NoResultException e) { http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/3abd4be2/security-admin/src/main/resources/META-INF/jpa_named_queries.xml ---------------------------------------------------------------------- diff --git a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml index be9b69e..a75ca93 100644 --- a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml +++ b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml @@ -605,7 +605,7 @@ </named-query> <!-- XXUserPermission --> - <named-query name="XXGroupPermission.findByGroupPermissionId"> + <named-query name="XXGroupPermission.findByGroupId"> <query>SELECT obj FROM XXGroupPermission obj WHERE obj.groupId=:groupId </query> http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/3abd4be2/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java ---------------------------------------------------------------------- diff --git a/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java b/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java index a7b6bb9..37dddee 100644 --- a/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java +++ b/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java @@ -724,6 +724,11 @@ public class TestXUserMgr { List<XXGroupGroup> xXGroupGroups = new ArrayList<XXGroupGroup>(); Mockito.when(daoManager.getXXGroupGroup()).thenReturn(xXGroupGroupDao); Mockito.when(xXGroupGroupDao.findByGroupId(userId)).thenReturn(xXGroupGroups); + //update XXGroupPermission + XXGroupPermissionDao xXGroupPermissionDao= Mockito.mock(XXGroupPermissionDao.class); + Mockito.when(daoManager.getXXGroupPermission()).thenReturn(xXGroupPermissionDao); + List<XXGroupPermission> xXGroupPermissions=new ArrayList<XXGroupPermission>(); + Mockito.when(xXGroupPermissionDao.findByGroupId(vXGroup.getId())).thenReturn(xXGroupPermissions); //update XXPolicyItemUserPerm XXPolicyDao xXPolicyDao = Mockito.mock(XXPolicyDao.class); List<XXPolicy> xXPolicyList = new ArrayList<XXPolicy>(); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/3abd4be2/src/main/assembly/admin-web.xml ---------------------------------------------------------------------- diff --git a/src/main/assembly/admin-web.xml b/src/main/assembly/admin-web.xml index 4f7711c..ca68ac6 100644 --- a/src/main/assembly/admin-web.xml +++ b/src/main/assembly/admin-web.xml @@ -339,6 +339,7 @@ <include>upgrade.sh</include> <include>update_property.py</include> <include>ranger_credential_helper.py</include> + <include>deleteUserGroupUtil.py</include> </includes> <fileMode>544</fileMode> </fileSet>
