You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ga...@apache.org on 2016/03/16 13:19:31 UTC

incubator-ranger git commit: RANGER-806 : Ranger utility to delete users from Ranger

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 <pr...@freestoneinfotech.com>
Authored: Wed Mar 16 12:13:17 2016 +0530
Committer: Gautam Borad <ga...@apache.org>
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>