#!/usr/bin/env python3 import os import xmlrpc.client import ssl import sys import syslog import pwd import grp import getpass import signal signal.signal(signal.SIGINT,signal.SIG_IGN) class AccessControlCliManager(object): def __init__(self,mode,skipAdmin): self.groupsInfo={} self.isAccessDenyGroupEnabled=False self.usersInfo={} self.isAccessDenyUserEnabled=False self.usersFilter=['root'] self.currentUser="" self.unattendedMode=mode self.skipAdmin=skipAdmin self.groupsUnLockedCount=0 self.usersUnLockedCount=0 self.cdcInfo={} self.cdcCode="" self.isCDCAccessControlAllowed=False self.isAccessDenyCDCEnabled=False self.credential="" self.createClient('localhost') #def __init__ def createClient(self,server): context=ssl._create_unverified_context() self.n4dClient=xmlrpc.client.ServerProxy("https://%s:9779"%server,allow_none=True,context=context) self._getCurrentUser() self._getInfo() #def createClient def getCredential(self): if self.currentUser!="": password=getpass.getpass(' [Access-Control]: Enter your password:') validationError=False try: ret=self.n4dClient.validate_user(self.currentUser,password) if ret[0]: self.credential=[self.currentUser,password] else: validationError=True except Exception as e: validationError=True if validationError: msg="Authentication failed. Unable to execute action" self.writeLog(msg) print(" [Access-Control]: %s"%msg) sys.exit(1) else: try: with open('/etc/n4d/key','r') as fd: key=fd.readline().strip() self.credential=key except: print(' [Access-Control]: You need root privilege to run this tool') sys.exit(1) #def getCredential def showCurrentConfig(self,optionInfo): self.writeLog("- Action: get information about %s"%optionInfo) self.getCredential() if optionInfo=="all" or optionInfo=="groups": print(' [Access-Control]: Current access control by group configuration') print(' - Access control by group activated: %s'%(str(self.isAccessDenyGroupEnabled))) print(' - Groups with restriced access:') for item in self.groupsInfo: print(' - %s: locked access %s'%(item,str(self.groupsInfo[item]["isLocked"]))) if optionInfo=="all" or optionInfo=="users": print(' [Access-Control]: Current access control by user configuration') print(' - Access control by user activated: %s'%(str(self.isAccessDenyUserEnabled))) print(' - Users with restriced access:') if len(self.usersInfo)>0: for item in self.usersInfo: print(' - %s: locked access %s'%(item,str(self.usersInfo[item]["isLocked"]))) else: print(' - There is no user in users list') if optionInfo=="all" or optionInfo=="center": print(' [Access-Control]: Current access control by center configuration') if not self.isCDCAccessControlAllowed: print(' - Access control by center is currently not allowed') else: print(' - Access control by center activated: %s'%(str(self.isAccessDenyCDCEnabled))) if self.cdcCode!="": print(' - Current center code configured: %s'%(str(self.cdcCode))) else: print(' - Current center code configured: None') return 0 #def showCurrentConfig def lockGroup(self,groupsSelected): return self._changeGroupStatus(groupsSelected,'lock') #def lockGroup def unlockGroup(self,groupsSelected): return self._changeGroupStatus(groupsSelected,'unlock') #def unlockGroup def disableControlGroup(self): if self.isAccessDenyGroupEnabled: if not self.unattendedMode: response=input(' [Access-Control]: Do you want to disable group access control? (yes/no)): ').lower() else: response='yes' if response.startswith('y'): self.writeLog("Changes in configuration of access control by Group:") self.writeLog("- Action: disable access control by group") self.getCredential() ret=self.n4dClient.disableAccessDenyGroup(self.credential,"AccessControlManager") if ret["status"]: self.writeLog("- Disable access control by group: Change apply successful") print(' [Access-Control]: Action completed successfull') self._getGroupInfo("End") return 0 else: self.writeLog("- Error applying changes: %s"%e.code) print(' [Access-Control]: Error. Unable to disable group access control') return 1 else: print(' [Access-Control]: Action canceled') return 0 else: print(' [Access-Control]: Access control by groups already disable. Nothing to do') return 0 #def disableControlGroup def enableControlGroup(self): if not self.isAccessDenyGroupEnabled: if self._checkIfExistsLock("groups"): if not self.unattendedMode: response=input(' [Access-Control]: Do you want to enable group access control? (yes/no)): ').lower() else: response='yes' if response.startswith('y'): self.writeLog("Changes in configuration of access control by Group:") self.writeLog("- Action: enable access control by group") self.getCredential() ret=self.n4dClient.setGroupsInfo(self.credential,'AccessControlManager',self.groupsInfo) if ret['status']: self.writeLog("- Enable access control by group: Change apply successful") print(' [Access-Control]: Action completed successfull') self._getGroupInfo("End") return 0 else: self.writeLog("- Error applying changes: %s"%ret['msg']) print(' [Access-Control]: Error. Unable to activate group access control') return 1 else: print(' [Access-Control]: Action canceled') return 0 else: print(' [Access-Control]: There is no group with locked access. Is not possible to activate access control by group') return 0 else: print(' [Access-Control]: Access control by groups already enable. Nothing to do ') return 0 #def enableControlGroup def lockUser(self,usersSelected): return self._changeUserStatus(usersSelected,'lock') #def lockUsers def unlockUser(self,usersSelected): return self._changeUserStatus(usersSelected,'unlock') #def unlockUsers def disableControlUser(self): if self.isAccessDenyUserEnabled: if not self.unattendedMode: response=input(' [Access-Control]: Do you want to disable user access control? (yes/no)): ').lower() else: response='yes' if response.startswith('y'): self.writeLog("Changes in configuration of access control by User:") self.writeLog("- Action: disable access control by user") self.getCredential() ret=self.n4dClient.disableAccessDenyUser(self.credential,"AccessControlManager") if ret["status"]: self.writeLog("- Disable access control by user: Change apply successful") print(' [Access-Control]: Action completed successfull') self._getUserInfo("End") return 0 else: self.writeLog("- Error applying changes: %s"%ret['msg']) print(' [Access-Control]: Error. Unable to disable user access control') return 1 else: print(' [Access-Control]: Action canceled') return 0 else: print(' [Access-Control]: Access control by users already disable. Nothing to do') return 0 #def disableControlUser def enableControlUser(self): if not self.isAccessDenyUserEnabled: if self._checkIfExistsLock("users"): if not self.unattendedMode: response=input(' [Access-Control]: Do you want to enable user access control? (yes/no)): ').lower() else: response='yes' if response.startswith('y'): self.writeLog("Changes in configuration of access control by User:") self.writeLog("- Action: enable access control by user") self.getCredential() ret=self.n4dClient.setUsersInfo(self.credential,'AccessControlManager',self.usersInfo) if ret['status']: self.writeLog("- Enable access control by user: Change apply successful") print(' [Access-Control]: Action completed successfull') self._getUserInfo("End") return 0 else: self.writeLog("- Error applying changes: %s"%ret['msg']) print(' [Access-Control]: Error. Unable to activate user access control') return 1 else: print(' [Access-Control]: Action canceled') return 0 else: print(' [Access-Control]: There is no users with locked access. Is not possible to activate access control by user') return 0 else: print(' [Access-Control]: Access control by users already enable. Nothing to do ') return 0 #def enableControlUser def removeUserFromList(self,usersSelected): correctUsers=self._checkCorrectUsers(usersSelected) if correctUsers: if (len(usersSelected)==len(self.usersInfo)) and self.isAccessDenyUserEnabled: print(' [Access-Control]: This action will be disable access control by user') if not self.unattendedMode: response=input(' [Access-Control]: Do you want to delete indicated users from users list? (yes/no)): ').lower() else: response='yes' if response.startswith('y'): self.writeLog("Changes in configuration of access control by User:") self.writeLog("- Action: remove user from list") self.getCredential() ret=self._applyUserChanges(usersSelected,"remove") if ret['status']: self.writeLog("- New users with locked access: Changes apply successful") print(' [Access-Control]: Action completed successfull') self._getUserInfo("End") return 0 else: self.writeLog("- Error applying changes: %s"%ret['msg']) print(' [Access-Control]: Unable to delete indicated useres from users list') return 1 else: print(' [Access-Control]: Action canceled') return 0 else: print(' [Access-Control]: The users indicates to remove from users list are not correct. See currentconfig users to get correct users') return 1 #def removeUser def removeUserList(self): if len(self.usersInfo)>0: if self.isAccessDenyUserEnabled: print(' [Access-Control]: This action will be disable access control by user') if not self.unattendedMode: response=input(' [Access-Control]: Do you want to delete users list? (yes/no)): ').lower() else: response='yes' if response.startswith('y'): self.writeLog("Action: Removed user list") self.getCredential() self.usersInfo={} ret=self.n4dClient.setUsersInfo(self.credential,"AccessControlManager",self.usersInfo) if ret["status"]: print(' [Access-Control]: Action completed successfull') self._getUserInfo("End") return 0 else: self.writeLog("Error removing user list: %s"%ret["msg"]) print(' [Access-Control]: Unable to delete users list') return 1 else: print(' [Access-Control]: Action canceled') return 0 else: print(' [Access-Control]: User list not exist. Nothing to do') return 0 #def removeUserList def setCenter(self,cdcCode): return self._changeCDCCode('set',cdcCode) #def setCenter def removeCenter(self): return self._changeCDCCode('remove') #def removeCenter def disableControlCenter(self): if self.isCDCAccessControlAllowed: if self.isAccessDenyCDCEnabled: if not self.unattendedMode: response=input(' [Access-Control]: Do you want to disable center access control? (yes/no)): ').lower() else: response='yes' if response.startswith('y'): self.writeLog("Changes in configuration of access control by CDC:") self.writeLog("- Action: disable access control by CDC") self.getCredential() ret=self.n4dClient.disableAccessDenyCDC(self.credential,"AccessControlManager",True) if ret["status"]: self.writeLog("- Disable access control by CDC: Change apply successful") print(' [Access-Control]: Action completed successfull') self._getCDCInfo("End") return 0 else: self.writeLog("- Error applying changes: %s"%ret["msg"]) print(' [Access-Control]: Error. Unable to disable CDC access control') return 1 else: print(' [Access-Control]: Action canceled') return 0 else: print(' [Access-Control]: Access control by center already disable. Nothing to do') return 0 else: print(' - Access control by center is currently not allowed') return 1 #def disableControlCenter def enableControlCenter(self): if self.isCDCAccessControlAllowed: if not self.isAccessDenyCDCEnabled: if self.cdcCode!="": if not self.unattendedMode: response=input(' [Access-Control]: Do you want to enable center access control? (yes/no)): ').lower() else: response='yes' if response.startswith('y'): self.writeLog("Changes in configuration of access control by CDC:") self.writeLog("- Action: enable access control by CDC") self.getCredential() self.cdcInfo["accessControlEnabled"]=True ret=self.n4dClient.setCDCInfo(self.credential,"AccessControlManager",self.cdcInfo) if ret["status"]: self.writeLog("- Enable access control by CDC: Change apply successful") print(' [Access-Control]: Action completed successfull') self._getCDCInfo("End") return 0 else: self.writeLog("- Error applying changes: %s"%ret["msg"]) print(' [Access-Control]: Error. Unable to activate center access control') return 1 else: print(' [Access-Control]: Action canceled') return 0 else: print(' [Access-Control]: There is no center code in previous configuration. Is not possible to activate access control by center') return 0 else: print(' [Access-Control]: Access control by center already enable. Nothing to do ') return 0 else: print(' - Access control by center is currently not allowed') return 1 #def enableControlCenter def _getInfo(self): self._getGroupInfo() self._getUserInfo() self._getCDCInfo() #def _getInfo def _getGroupInfo(self,step="Initial"): self.writeLog("Access Control by Group. %s configuration:"%step) self.isAccessDenyGroupEnabled=self.n4dClient.isAccessDenyGroupEnabled(self.credential,"AccessControlManager")["status"] self.writeLog("- Access control by group activated: %s"%(str(self.isAccessDenyGroupEnabled))) if step=="Initial": initLoad=True else: initLoad=False self.groupsInfo=self.n4dClient.getGroupsInfo(self.credential,"AccessControlManager",initLoad)["data"] self.writeLog("- Groups with restricted access: ") for item in self.groupsInfo: self.writeLog(" - %s: locked access %s"%(item,str(self.groupsInfo[item]["isLocked"]))) #def _getGroupInfo def _getUserInfo(self,step="Initial"): self.writeLog("Access Control by User. %s configuration:"%step) self.isAccessDenyUserEnabled=self.n4dClient.isAccessDenyUserEnabled(self.credential,"AccessControlManager")["status"] self.writeLog("- Access Control by User activated: %s"%(str(self.isAccessDenyUserEnabled))) self.usersInfo=self.n4dClient.getUsersInfo(self.credential,"AccessControlManager")["data"] self.writeLog("- Users with restricted access: ") if len(self.usersInfo)>0: for item in self.usersInfo: self.writeLog(" - %s: locked access %s"%(item,str(self.usersInfo[item]["isLocked"]))) else: self.writeLog(" - There is no user list") #def _getUserInfo def _getCDCInfo(self,step="Initial"): self.writeLog("Access Control by Center. %s configuration:"%step) self.isCDCAccessControlAllowed=self.n4dClient.isCDCAccessControlAllowed(self.credential,"AccessControlManager")["status"] self.writeLog("- Access Control by CDC allowed: %s"%(str(self.isCDCAccessControlAllowed))) self.isAccessDenyCDCEnabled=self.n4dClient.isAccessDenyCDCEnabled(self.credential,"AccessControlManager")["status"] self.writeLog("- Access Control by CDC enabled: %s"%(str(self.isAccessDenyCDCEnabled))) self.cdcInfo=self.n4dClient.getCDCInfo(self.credential,"AccessControlManager")["data"] if self.cdcInfo["code"]!="": self.cdcCode=self.cdcInfo["code"] currentCode=self.cdcCode else: currentCode=None self.writeLog("- Center code to control access: %s"%(str(currentCode))) #def _getCDCInfo def _changeGroupStatus(self,groupsSelected,action): correctGroups=self._checkCorrectGroups(groupsSelected) if correctGroups: currentStatusChanged=self._checkCurrentConfiguration('groups',groupsSelected,action) if currentStatusChanged: if action=="lock" and not self.isAccessDenyGroupEnabled: print(' [Access-Control]: This action will be activate access control by group') elif action=="unlock" and (self.groupsUnLockedCount==len(self.groupsInfo)) and self.isAccessDenyGroupEnabled: print(' [Access-Control]: This action will be disable access control by group') if not self.unattendedMode: response=input(' [Access-Control]: Do you want to %s access to the indicated groups? (yes/no)): '%action).lower() else: response='yes' if response.startswith('y'): self.writeLog("Changes in configuration of access control by Group:") self.writeLog("- Action: change group list %s"%action) self.getCredential() ret=self._applyGroupChanges(groupsSelected,action) if ret["status"]: self.writeLog("- New groups with locked access: Changes apply successful") print(' [Access-Control]: Action completed successfull') self._getGroupInfo("End") return 0 else: self.writeLog("- Error applying changes: %s"%ret["msg"]) print(' [Access-Control]: Unable to %s access to the indicated groups'%action) return 1 else: print(' [Access-Control]: Action canceled') return 0 else: print(' [Access-Control]: The indicated groups are already %sed. Nothing to do'%action) return 0 else: print(' [Access-Control]: The groups indicates to %s their acces are not correct. See currentconfig groups to get correct groups'%action) return 1 #def _changeGroupStatus def _checkCorrectGroups(self,groupsSelected): for item in groupsSelected: if item not in self.groupsInfo.keys(): return False return True #def _checkCorrectGroups def _changeUserStatus(self,usersSelected,action): correctUsers=self._checkCorrectUsers(usersSelected) adminUsers="" if not correctUsers: if action=="unlock": print(' [Access-Control]: The users indicates to %s their acces are not correct. See currentconfig users to get correct users'%action) return 1 else: ret=self._checkIfUserIsCurrentUser(usersSelected) if ret[0]: for item in range(len(usersSelected)-1,-1,-1): try: if usersSelected[item] in ret[1]: usersSelected.pop(item) except: pass if len(usersSelected)==0 and action=="lock": print(' [Access-Control]: It is not possible to lock the user with which you are configuring the access control') return 0 else: adminInUsers=self._checkIfUserIsLocalAdmin(usersSelected) if adminInUsers[0]: if action=="lock": countAdminUsers=len(adminInUsers[1]) count=1 for item in adminInUsers[1]: if count0: return True else: return False #def _checkCurrentConfiguration def _checkCurrentCDCConfiguration(self,action,newValue=""): if action=="set": if newValue!=self.cdcCode: return True return False elif action=="remove": if self.cdcCode!="": return True else: return False #def _checkCurrentCDCConfiguration def _applyGroupChanges(self,groupsSelected,action): for item in self.groupsInfo: if item in groupsSelected: if action=="lock": self.groupsInfo[item]["isLocked"]=True else: self.groupsInfo[item]["isLocked"]=False return self.n4dClient.setGroupsInfo(self.credential,"AccessControlManager",self.groupsInfo) #def _applyGroupChanges def _applyUserChanges(self,usersSelected,action): if action!="remove": for item in self.usersInfo: if item in usersSelected: if action=="lock": self.usersInfo[item]["isLocked"]=True elif action=="unlock": self.usersInfo[item]["isLocked"]=False if action=="lock": for item in usersSelected: if item not in self.usersInfo.keys(): self.usersInfo[item]={} self.usersInfo[item]["isLocked"]=True else: for item in usersSelected: if item in self.usersInfo.keys(): del self.usersInfo[item] return self.n4dClient.setUsersInfo(self.credential,"AccessControlManager",self.usersInfo) #def _applyUserChanges def _checkIfUserIsLocalAdmin(self,usersSelected): adminGroups=["sudo","admins","adm"] match=0 adminUser=[] for item in usersSelected: if item not in self.usersInfo.keys(): try: gid = pwd.getpwnam(item).pw_gid groups_gid=os.getgrouplist(item,gid) user_groups=[grp.getgrgid(x).gr_name for x in groups_gid] for element in user_groups: if element in adminGroups: match+=1 adminUser.append(item) break except: pass if match>0: return [True,adminUser] else: return [False,adminUser] #def _checkIfUserIsLocalAdmin def _applyCDCChanges(self,action,cdcCode=""): if action=="set": if not self.cdcInfo["accessControlEnabled"]: self.cdcInfo["accessControlEnabled"]=True self.cdcInfo["code"]=cdcCode elif action=="remove": self.cdcInfo={} return self.n4dClient.setCDCInfo(self.credential,"AccessControlManager",self.cdcInfo) #def _applyCDCChanges def _getCurrentUser(self): sudoUser="" loginUser="" pkexecUser="" try: sudoUser=(os.environ["SUDO_USER"]) except: pass try: loginUser=os.getlogin() except: pass try: cmd="id -un $PKEXEC_UID" p=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE) pkexecUser=p.communicate()[0].decode().strip() except Exception as e: pass if pkexecUser!="root" and pkexecUser!="": self.currentUser=pkexecUser if pkexecUser not in self.usersFilter: self.usersFilter.append(pkexecUser) elif sudoUser!="root" and sudoUser!="": self.currentUser=sudoUser if sudoUser not in self.usersFilter: self.usersFilter.append(sudoUser) else: self.currentUser=loginUser if loginUser not in self.usersFilter: self.usersFilter.append(loginUser) self.writeLog("Init session in lliurex-access-control CLI") if self.currentUser!="": self.writeLog("User login in CLI: %s"%self.currentUser) else: self.writeLog("User login in CLI: No current user detected. A script may have been executed at login") self.writeLog("Unattended Mode: %s"%(str(self.unattendedMode))) self.writeLog("Skip Admin: %s"%(str(self.skipAdmin))) #def _getCurrentUser def _checkIfUserIsCurrentUser(self,usersSelected): currentUserList=[] for item in usersSelected: if item in self.usersFilter: currentUserList.append(item) if len(currentUserList)>0: return [True,currentUserList] else: return [False,currentUserList] #def _checkIfUserIsCurrentUser def _checkIfExistsLock(self,option): if option=="groups": data=self.groupsInfo else: data=self.usersInfo for item in data: if data[item]["isLocked"]: return True return False #def _checkIfExistsLock def writeLog(self,msg): syslog.openlog("ACCESS-CONTROL") syslog.syslog(msg) #def writeLog #class AccessControlCliManager