def listinstalled(summary=False): options = '-f=${binary:Package};${Version};${Architecture}' + ( ';${binary:Summary}\n' if summary else '\n') command = ['dpkg-query', options, '-W'] try: output = check_output(command, stderr=PIPE, universal_newlines=True).splitlines() except CalledProcessError as e: return command_error(e, command) except FileNotFoundError as e: return command_error(e, command) #Lista di chiavi per le informazioni sull'app keys = ['name', 'version', 'architecture'] if summary: keys.append('summary') #ConterrĂ una lista di dizionari con tutte le app installate nel sistema pkgs = list() #Inserimento valori nella lista apps() for i in output: appinfo = i.split(';') pkgs.append(dict(zip(keys, appinfo))) return command_success(data=pkgs)
def getuser(user): try: command = ['getent', 'passwd', user] userinfo = check_output(command, stderr=PIPE, universal_newlines=True).splitlines() except CalledProcessError as e: return command_error(e, command) #Info sull'utente dal file /etc/passwd userinfo = userinfo[0].split(':') #Getting user groups usergroups = getusergroups(user) if usergroups['returncode'] is 0: usergroups = usergroups['data'] else: return usergroups #Returns the entire error dictionary as created by "command_error" function return command_success( data=dict({ 'uname': userinfo[0], 'canlogin': '******' if userinfo[1] == 'x' else 'no', 'uid': userinfo[2], 'gid': userinfo[3], 'geco': userinfo[4].split(','), 'home': userinfo[5], 'shell': userinfo[6], 'group': usergroups.pop(0), #Main user group 'groups': usergroups if usergroups else "< No groups >" }))
def aptshow(pkgname, onlydependences=False): mode = 'depends' if onlydependences else 'show' try: command = ['apt-cache', mode, pkgname] output = check_output(command, stderr=PIPE, universal_newlines=True) except CalledProcessError as e: return command_error(e, command) if onlydependences: #Remove the first line (header) toreturn = re.sub('^.*\\n', '', output) else: #On multiple results only keep the first one output = output.split('\n\n')[0] output = output.splitlines( ) #<-- We use splitlines() here because onlydependences does not need a split-lined output #Check whether the package is installed or not isinstalled = None try: command = ['dpkg', '-s', pkgname] check_call(command) except CalledProcessError as e: isinstalled = False if isinstalled is None: isinstalled = True #Removing useless lines linestomantain = [ 'Package:', 'Version:', 'Priority:', 'Section:', 'Origin:', 'Installed-Size:', 'Depends:', 'Description', ' ' ] output = list( filter( lambda line: any(line.startswith(s) for s in linestomantain), output)) #Merging all of descrition lines i = 0 n = len(output) while i < n: if output[i].startswith(' '): output[i - 1] = output[i - 1] + output[i] #<-- Merge lines del output[i] #<-- Delete current line n -= 1 else: i += 1 #Converting list to dictionary toreturn = dict() for line in output: dictelems = line.split(':', maxsplit=1) toreturn.update({dictelems[0]: dictelems[1]}) #Is this package installed? toreturn.update({'Installed': 1 if isinstalled else 0}) return command_success(data=toreturn)
def updatedb(): try: command = ['updatedb'] check_call(command, stderr=PIPE) except CalledProcessError as e: return command_error( e, command ) return command_success()
def addrepo(content, name): logid = mongolog(locals()) filename = '/etc/apt/sources.list.d/' + name + '.list' repofile = open(filename, 'a') repofile.write(content + '\n') repofile.close() return command_success(logid=logid)
def adddefaultcron(command, cronspath, name): #New cron gets a random name if user did not provide it if not name: name = getcronname() logid = mongolog(locals()) with open(cronspath + name, 'w') as newcron: newcron.write(command + '\n') return command_success(data=cronspath + name, logid=logid)
def hostname(newhostname=""): command = ['hostname'] if newhostname: logid = mongolog( locals() ) command.append(newhostname) try: hostname = check_output(command, stderr=PIPE, universal_newlines=True) except CalledProcessError as e: if newhostname: return command_error( e, command, logid ) else: return command_error( e, command ) if newhostname: return command_success( logid=logid ) else: return command_success( data=hostname )
def aptupdate(): logid = mongolog(locals()) try: command = ['apt-get', 'update'] check_call(command) except CalledProcessError as e: return command_error(e, command, logid) return command_success(logid=logid)
def ifacedown(iface): logid = mongolog(locals()) command = ['ifconfig', iface, 'down'] try: check_call(command) except CalledProcessError as e: return command_error(e, command, logid) return command_success(logid=logid)
def getshells(): with open('/etc/shells') as opened: shells = opened.read().splitlines() #Removing comment lines shells = list(filter(lambda shell: not shell.startswith('#'), shells)) #Manually Appending dummy shells shells = shells + ['/usr/sbin/nologin', '/bin/false'] return command_success(data=shells)
def getusers(): with open('/etc/passwd', 'r') as opened: passwd = opened.read().splitlines() users = dict() for line in passwd: line = line.split(':', 3) uname = line[0] uid = line[2] users[uid] = uname return command_success(data=users)
def getobjs(objtype): availabledir = objtype + '-available/' enableddir = objtype + '-enabled/' objs = list() #Getting enabled vhosts and appending to vhosts list as dictionary enabled = set(os.listdir(apacheconfdir + enableddir)) for obj in enabled: objs.append({'filename': obj, 'active': 1}) #Gets nonactive vhosts and appending to vhosts list as dictionary notactive = set(os.listdir(apacheconfdir + availabledir)).difference(enabled) for obj in notactive: objs.append({'filename': obj, 'active': 0}) ##### ONLY FOR VHOSTS ##### #Gathering object information only if objstype == "site" if objtype is "sites": #Gathering vhosts information to fill the list for obj in objs: #"vhostcontent" mantains all vhost file content with open(apacheconfdir + availabledir + obj['filename']) as opened: vhostcontent = opened.read().splitlines() i = 0 for line in vhostcontent: line = line.lstrip() linestosearch = ('Alias', 'DocumentRoot', 'ServerName', 'ServerAlias') #If any of this words in vhost file add the entire splitted line to the vhost dict if any(line.startswith(s) for s in linestosearch): #A vhost can handle multiple ServerAlias but dict() cannot accept multiple key with the same string #so we're going to add an incremental number to the key "ServerAlias" if 'ServerAlias' in line: line = re.sub('ServerAlias', 'ServerAlias' + str(i), line) i += 1 line = line.split(None, maxsplit=1) #vhost dict is a pointer to the original dict in vhosts list, hence an update here means an update to the original dict obj.update({line[0]: line[1]}) return command_success(data=objs)
def ifacestat(iface="", namesonly=False): command = ['ifconfig', '-a'] if iface: command.append(iface) try: output = check_output(command, stderr=PIPE, universal_newlines=True) except CalledProcessError as e: return command_error(e, command) #After this split each list item contains an interface specs output = output.split('\n\n') #Removing empty line at the end del output[-1] #List or dict to be returned #If namesonly=True is a list, dict instead ifaces = list() if namesonly else dict() for iface in output: #Splitting interface lines iface = iface.splitlines() #Getting iface name on first line #We need to split first line and reinsert the second item in the original list firstline = iface.pop(0).split(None, maxsplit=1) #Returns a list cotaining all interfaces name if namesonly: ifaces.append(firstline[0]) #Returns a dict containig all interfaces specs else: iface.insert(0, firstline[1]) #Cutting out useless lines i = 0 #Using "enumerate" because we need to modify the original list for index, value in enumerate(iface): #"i" indicates where to stop cutting i += 1 #Removing leading and trailing spaces iface[index] = iface[index].strip() if iface[index].startswith('UP') or iface[index].startswith( 'DOWN'): break #A dictionary where the key is the interface name and the value is part of the lines related to such interface ifaces.update({firstline[0]: iface[:i]}) # '\n'.join(iface[:i]) }) return command_success(data=ifaces)
def listcrontabs(): basedir = '/etc/' paths = [ 'cron.d', 'cron.daily', 'cron.hourly', 'cron.monthly', 'cron.weekly' ] cronlist = dict() for path in paths: flist = os.listdir(basedir + path) flist.remove('.placeholder') cronlist.update({path: flist}) return command_success(data=cronlist)
def manageobjs(filename, op): logid = mongolog(locals()) command = [op, filename] try: #Shrinks the output --------. # | # v check_call(command, stdout=DEVNULL) except CalledProcessError as e: return command_error(e, command, logid) return command_success(logid=logid)
def locate(name, insensitive=True): #Cannot search on empty string if not name: return command_error( returncode=255, stderr='Empty search string not allowed' ) try: command = ['locate', '-i', name] if insensitive is False: command.pop(1) found = check_output(command, stderr=PIPE, universal_newlines=True).splitlines() except CalledProcessError as e: return command_error( e, command ) return command_success( data=found )
def getexternalrepos(): repospath = '/etc/apt/sources.list.d/' reposfiles = os.listdir(repospath) #Removing file that ends with '.save' reposfiles = list( filter(lambda item: not item.endswith('.save'), reposfiles)) #List to return repos = list() for filename in reposfiles: with open(repospath + filename) as opened: repos.append({'filename': filename, 'lines': opened.read()}) return command_success(data=repos)
def getnewifacealiasname(iface): ifaces = ifacestat(namesonly=True) if ifaces['returncode'] is 0: ifaces = ifaces['data'] aliasid = 0 for item in ifaces: if item.startswith( iface + ':' ): #By default aliases will be parsed in numeric ascending order due to ifconfig output item = int(re.sub('.*:', '', item)) if aliasid is item: aliasid += 1 else: break return command_success(data=iface + ':' + str(aliasid))
def adduser(user, password, shell="/bin/bash"): logid = mongolog(locals()) if not shell: return command_error( returncode=200, stderr="String containing new shell name cannot be empty", logid=logid) try: command = ['useradd', '-m', '-p', password, '-s', shell, user] check_output(command, stderr=PIPE, universal_newlines=True) except CalledProcessError as e: return command_error(e, command, logid) return command_success(logid=logid)
def getgroups(namesonly=False): with open('/etc/group', 'r') as opened: etcgroup = opened.read().splitlines() groups = list() if namesonly: groups = list(map(lambda line: line.split(':')[0], etcgroup)) else: for line in etcgroup: line = line.split(':') groups.append({ 'gname': line[0], 'gid': line[2], 'members': line[3].split(',') }) return command_success(data=groups)
def getroutes(): command = ['route', '-n'] try: output = check_output(command, stderr=PIPE, universal_newlines=True).splitlines() except CalledProcessError as e: return command_error(e, command) #Removing useless header output.pop(0) #Storing useful header to use later header = output.pop(0).split() routes = list(map(lambda route: dict(zip(header, route.split())), output)) return command_success(data=routes)
def aptremove(pkgname, purge=False): logid = mongolog(locals(), {'dependencies': aptshow(pkgname, onlydependences=True)}) command = ['apt-get', 'purge' if purge else 'remove', '-y', pkgname] environ = { 'DEBIAN_FRONTEND': 'noninteractive', 'PATH': os.environ.get('PATH') } try: check_call(command, env=environ) #stdout=open(os.devnull, 'wb'), stderr=STDOUT) except CalledProcessError as e: return command_error(e, command, logid) return command_success(logid=logid)
def ifaceup(iface, address="", netmask="", broadcast=""): logid = mongolog(locals()) command = ['ifconfig', iface] if address: command.append(address) if netmask: command = command + ['netmask', netmask] if broadcast: command = command + ['broadcast', broadcast] command.append('up') try: check_output = check_call(command, stderr=PIPE, universal_newlines=True) except CalledProcessError as e: return command_error(e, command, logid) return command_success(logid=logid)
def updateuserpass(user, password): #We literally cannot store password in mongo log, #hence here we are removing password from locals() localsvar = locals() del localsvar['password'] logid = mongolog(localsvar) try: command = ['echo', user + ':' + password] p1 = Popen(command, stdout=PIPE) command = ['/usr/sbin/chpasswd'] p2 = Popen(command, stdin=p1.stdout) p1.stdout.close() except CalledProcessError as e: return command_error(e, command, logid) return command_success(logid=logid)
def addusertogroups(user, *groups): #Logging operation to mongo first userinfo = getuser(user) if not userinfo['returncode'] is 0: return userinfo userinfo = userinfo['data'] logid = mongolog(locals(), userinfo) try: for group in groups: command = ['adduser', user, group] check_call(command) except CalledProcessError as e: return command_error(e, command, logid) #ObjectID of mongo return command_success(logid=logid)
def getusergroups(user): command = ['groups', user] try: usergroups = check_output(command, stderr=PIPE, universal_newlines=True).splitlines() except CalledProcessError as e: command_error(e, command) # .------Removing username from list # | .----------. # V V | usergroups = re.sub('^.*: ', '', usergroups[0]) #Only first line contains the groups usergroups = usergroups.split(' ') return command_success(data=usergroups)
def removeuser(user, removehome=False): userinfo = getuser(user) if userinfo['returncode'] is 0: userinfo = userinfo['data'] else: return userinfo logid = mongolog(locals(), userinfo) try: command = ['deluser', user] if removehome: command.append('--remove-home') check_output(command, stderr=PIPE, universal_newlines=True) except CalledProcessError as e: return command_error(e, command, logid) return command_success(logid=logid)
def getusernotgroups(user): #Getting all system groups groups = getgroups(namesonly=True) if groups['returncode'] is 0: groups = groups['data'] else: return groups #Getting user specific groups usergroups = getusergroups(user) if usergroups['returncode'] is 0: usergroups = usergroups['data'] else: return usergroups usernotgroup = list( filter(lambda group: not any(s in group for s in usergroups), groups)) return command_success(data=usernotgroup)
def addcron(command, name="", user="******", minute='*', hour='*', dom='*', month='*', dow='*'): cronspath = '/etc/cron.d/' #New cron gets a random name if user did not provide it if not name: name = getcronname() logid = mongolog(locals()) with open(cronspath + name, 'w') as newcron: newcron.write(minute + ' ' + hour + ' ' + dom + ' ' + month + ' ' + dow + ' ' + user + ' ' + command + '\n') return command_success(data=cronspath + name, logid=logid)
def delroute(route): logid = mongolog(locals()) if not type(route) is type(dict()): command_error( returncode=202, stderr='delroute function can only accept a dictionary as argument', logid=logid) command = [ 'route', 'del', '-net', route['Destination'], 'netmask', route['Genmask'], 'gw', route['Gateway'] ] try: check_call(command) except CalledProcessError as e: return command_error(e, command, logid) return command_success(logid=logid)