# -*- coding: utf-8 # # manage clientsdb.json #import site packages import json import hmac import bcrypt #import local packages import ioconfig import utils def addclient(vmid, vmname, clientid, clientname, clientemail, vmpass): """ add new client with the requested vm to the clientsdb.json """ clientsdb = readclientsdb() if str(clientid) in clientsdb: ioconfig.logger.info('clients> client ' + clientid + ' already exists. merging.') else: ioconfig.logger.info('clients> client ' + clientid + ' does not exist. creating.') vcard = { 'name':str(clientname), 'email':str(clientemail) } newclient = { str(clientid):vcard } clientsdb.update(newclient) ioconfig.logger.info('clients> vmid {} owner set to {} (id: {}, email: {})'.format(vmid, clientname, clientid, clientemail)) #create initial vm template vmdata = { 'hostname':str(vmname), 'vmid':str(vmid), 'ownerid':str(clientid) } clientsdb[str(clientid)][str(vmid)] = vmdata writeclientsdb(clientsdb) #set password for the first time... setencpasswd(vmname, vmpass) def setencpasswd(vmname, newpass): """ setup a new management password """ salt = bcrypt.gensalt() b_newpass = newpass.encode('utf-8') encpasswd = bcrypt.hashpw(b_newpass, salt).decode('utf-8') try: clientsdb = readclientsdb() #print(clientsdb) path = utils.get_path(clientsdb, vmname) #print(path) c_id = str(path[0]) v_id = str(path[1]) #check the returned path with forward query query = clientsdb[c_id][v_id]['hostname'] except: raise if query != vmname: ioconfig.logger.critical('clients> test query returns different vmname! check clients.json consistency!') raise else: clientsdb[c_id][v_id]['encpasswd'] = encpasswd ioconfig.logger.info('clients> {} (clientid: {}, vmid: {}) got its management password changed!'.format(query, c_id, v_id)) writeclientsdb(clientsdb) #TODO: change lxc container password def validate(clientemail, srvpass): """ return vmid or false if credentials match something in clientdb. useful for authing extrnal admin panels """ try: clientsdb = readclientsdb() path = utils.get_path(clientsdb, clientemail) c_id = str(path[0]) #check the returned path with forward query ioconfig.logger.info('clients> {} was found with clientid: {}'.format(clientemail, c_id)) except: raise ioconfig.logger.warning('clients> {} was not found in the database!'.format(clientemail)) #log bad ips here... return False vmlist = clientsdb[c_id] #clear unused objects. perhaps there is a better way to do this but im kinda anxious today... vmlist.pop('name') vmlist.pop('email') #try each vmid owned by this user for a password match for vmid,data in vmlist.items(): print(vmid) print(data) #try to capture the encrypted password encpass = data['encpasswd'] b_srvpass = srvpass.encode('utf-8') b_encpass = encpass.encode('utf-8') if (hmac.compare_digest(bcrypt.hashpw(b_srvpass, b_encpass), b_encpass)): #login successful ioconfig.logger.info('clients> {} was validated successfully by {}'.format(vmid, clientemail)) response = { 'vmid':vmid } else: ioconfig.logger.warning('clients> {} ACCESS DENIED!'.format(vmid)) #cant compare password response = { } #TODO: this will require major rewrite again.. or it will fail to auth 2 machines with same password. lame.. return response def vmowner(vmid, vmname, verbose): """ find the owner of the vm """ clientsdb = readclientsdb() try: clientid = utils.find_rec(clientsdb, str(vmid))[0]['ownerid'] clientname = clientsdb[str(clientid)]['name'] except: raise clientid = '0' #unknown owner clientname = 'unknown' if verbose: ioconfig.logger.info('clients> the owner of ' + str(vmid) + ' (' + vmname + ') is ' + str(clientid) + ' (' + clientname + ')') return clientid def readclientsdb(): """ read client db """ try: with open('clients.json') as dbr: clientsdb = json.load(dbr) dbr.close() except: clientsdb = {} ioconfig.logger.warning('clients> initializing...') #writeclientsdb(clientsdb) return clientsdb def writeclientsdb(clientsdb): """ write db """ with open('clients.json', 'w') as dbw: json.dump(clientsdb, dbw) dbw.close() if __name__ == '__main__': #setencpasswd('srv.test1.com', 'todos') validate('daniel@deflax.net', 'todos')