# HG changeset patch # User mb # Date 1391001497 -3600 # Node ID 59f1d824a07033b2172e2fdb515141d436431cee # Parent 495ebaa3af5b4212dd41cb248ebcccecb4ce56b6 iupdate template function and consolidation diff -r 495ebaa3af5b -r 59f1d824a070 OpenSecurity/bin/opensecurityd.py --- a/OpenSecurity/bin/opensecurityd.py Thu Jan 09 13:42:32 2014 +0100 +++ b/OpenSecurity/bin/opensecurityd.py Wed Jan 29 14:18:17 2014 +0100 @@ -63,11 +63,11 @@ '/sdvms/(.*)', 'os_sdvm', # http://localhost:8080/sdvms/[VMNAME] GET, DELETE '/vms', 'os_vms', # http://localhost:8080/vms GET '/vms/(.*)', 'os_vm', # http://localhost:8080/vms/[VMNAME] GET - '/', 'os_root' # http://localhost:8080/ GET + '/', 'os_root', # http://localhost:8080/ GET + '/update_template', 'os_update_template' # http://localhost:8080/update_template GET ) - -# ------------------------------------------------------------ + # ------------------------------------------------------------ # vars # Global VMManager instance @@ -221,6 +221,15 @@ res += "}" return res +class os_update_template: + """OpenSecurity '/update_template' handler + + - GET: update template vm + """ + + def GET(self): + #return gvm_mgr.guestExecute('SecurityDVM', 'sudo apt-get -y update') + return gvm_mgr.updateTemplate() # start if __name__ == "__main__": diff -r 495ebaa3af5b -r 59f1d824a070 OpenSecurity/bin/vmmanager.py --- a/OpenSecurity/bin/vmmanager.py Thu Jan 09 13:42:32 2014 +0100 +++ b/OpenSecurity/bin/vmmanager.py Wed Jan 29 14:18:17 2014 +0100 @@ -80,26 +80,6 @@ def isSDVMStarted(self, ip): return self.startNotifications.contains(ip) - - def execute(self, cmd, wait_return=True ): - if DEBUG: - print('trying to launch: ' + cmd) - process = Popen(cmd, stdout=PIPE, stderr=PIPE) #shell = True - if DEBUG: - print('launched: ' + cmd) - if not wait_return: - return [0, 'working in background', ''] - result = process.wait() - res_stdout = process.stdout.read(); - res_stderr = process.stderr.read(); - if DEBUG: - if res_stdout != "": - print res_stdout - if res_stderr != "": - print res_stderr - if result !=0: - raise VMManagerException(res_stderr) - return result, res_stdout, res_stderr def getVBoxManagePath(self): """get the path to the VirtualBox installation on this system""" @@ -115,7 +95,7 @@ # return hosty system properties def getSystemProperties(self): cmd = self.vboxManage + ' list systemproperties' - result = self.execute(cmd) + result = self.hostExecute(cmd) if result[1]=='': return None props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result[1].strip().splitlines())) @@ -123,12 +103,13 @@ # return the folder containing the guest VMs def getDefaultMachineFolder(self): - return self.systemProperties["Default machine folder"] + machineFolder = self.systemProperties["Default machine folder"] + return machineFolder #list the hostonly IFs exposed by the VBox host def getHostOnlyIFs(self): cmd = 'VBoxManage list hostonlyifs' - result = self.execute(cmd)[1] + result = self.hostExecute(cmd)[1] if result=='': return None props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result.strip().splitlines())) @@ -136,7 +117,7 @@ def listRSDS(self): cmd = 'VBoxManage list usbhost' - results = self.execute(cmd)[1] + results = self.hostExecute(cmd)[1] results = results.split('Host USB Devices:')[1].strip() items = list( "UUID:"+result for result in results.split('UUID:') if result != '') @@ -160,7 +141,14 @@ # list all existing VMs registered with VBox def listVM(self): cmd = 'VBoxManage list vms' - result = self.execute(cmd)[1] + result = self.hostExecute(cmd)[1] + vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines())) + return vms + + # list running VMs + def listRunningVMS(self): + cmd = 'VBoxManage list runningvms' + result = self.hostExecute(cmd)[1] vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines())) return vms @@ -194,63 +182,155 @@ # configures hostonly networking and DHCP server. requires admin rights def configureHostNetworking(self): #cmd = 'vboxmanage list hostonlyifs' - #self.execute(cmd) + #self.hostExecute(cmd) #cmd = 'vboxmanage hostonlyif remove \"VirtualBox Host-Only Ethernet Adapter\"' - #self.execute(cmd) + #self.hostExecute(cmd) #cmd = 'vboxmanage hostonlyif create' - #self.execute(cmd) + #self.hostExecute(cmd) cmd = 'VBoxManage hostonlyif ipconfig \"VirtualBox Host-Only Ethernet Adapter\" --ip 192.168.56.1 --netmask 255.255.255.0' - self.execute(cmd) + self.hostExecute(cmd) #cmd = 'vboxmanage dhcpserver add' - #self.execute(cmd) + #self.hostExecute(cmd) cmd = 'VBoxManage dhcpserver modify --ifname \"VirtualBox Host-Only Ethernet Adapter\" --ip 192.168.56.100 --netmask 255.255.255.0 --lowerip 192.168.56.101 --upperip 192.168.56.200' - self.execute(cmd) + self.hostExecute(cmd) #create new virtual machine instance based on template vm named SecurityDVM (\SecurityDVM\SecurityDVM.vmdk) def createVM(self, vm_name): hostonly_if = self.getHostOnlyIFs() + cmd = 'VBoxManage createvm --name ' + vm_name + ' --ostype Debian --register' + self.hostExecute(cmd) + cmd = 'VBoxManage modifyvm ' + vm_name + ' --memory 512 --vram 10 --cpus 1 --usb on --usbehci on --nic1 hostonly --hostonlyadapter1 \"' + hostonly_if['Name'] + '\" --nic2 nat' + self.hostExecute(cmd) + cmd = 'VBoxManage storagectl ' + vm_name + ' --name SATA --add sata --portcount 2' + self.hostExecute(cmd) + return + + # attach storage image to controller + def storageAttach(self, vm_name): + if self.isStorageAttached(vm_name): + self.storageDetach(vm_name) machineFolder = self.getDefaultMachineFolder() - cmd = 'VBoxManage createvm --name ' + vm_name + ' --ostype Debian --register' - self.execute(cmd) - cmd = 'VBoxManage modifyvm ' + vm_name + ' --memory 512 --vram 10 --cpus 1 --usb on --usbehci on --nic1 hostonly --hostonlyadapter1 \"' + hostonly_if['Name'] + '\" --nic2 nat' - self.execute(cmd) - cmd = 'VBoxManage storagectl ' + vm_name + ' --name contr1 --add sata --portcount 2' - self.execute(cmd) - cmd = 'VBoxManage storageattach ' + vm_name + ' --storagectl contr1 --port 0 --device 0 --type hdd --medium \"'+ machineFolder + '\SecurityDVM\SecurityDVM.vmdk\"' #--mtype immutable - self.execute(cmd) + cmd = 'VBoxManage storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium \"'+ machineFolder + '\SecurityDVM\SecurityDVM.vmdk\"' + self.hostExecute(cmd) return + # return true if storage is attached + def isStorageAttached(self, vm_name): + info = self.getVMInfo(vm_name) + return (info['SATA-0-0']!='none') + + # detach storage from controller + def storageDetach(self, vm_name): + if self.isStorageAttached(vm_name): + cmd = 'VBoxManage storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium none' + self.hostExecute(cmd) + return + + def changeStorageType(self, filename, type): + cmd = 'VBoxManage modifyhd \"' + filename + '\" --type ' + type + self.hostExecute(cmd) + return + + # list storage snaphots for VM + def updateTemplate(self): + self.poweroffVM('SecurityDVM') + self.waitShutdown('SecurityDVM') + + # check for updates + self.genCertificateISO('SecurityDVM') + self.attachCertificateISO('SecurityDVM') + + self.storageDetach('SecurityDVM') + cmd = 'VBoxManage list hdds' + results = self.hostExecute(cmd)[1] + results = results.replace('Parent UUID', 'Parent') + items = list( "UUID:"+result for result in results.split('UUID:') if result != '') + + snaps = dict() + for item in items: + #print item + props = dict() + for line in item.splitlines(): + if line != "": + k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip() + props[k] = v; + snaps[props['UUID']] = props + + machineFolder = self.getDefaultMachineFolder() + template_storage = machineFolder + '\SecurityDVM\SecurityDVM.vmdk' + + # find template uuid + template_uuid = '' + for hdd in snaps.values(): + if hdd['Location'] == template_storage: + template_uuid = hdd['UUID'] + print 'found parent uuid ' + template_uuid + + # remove snapshots + for hdd in snaps.values(): + if hdd['Parent'] == template_uuid: + #template_uuid = hdd['UUID'] + print 'removing snapshot ' + hdd['UUID'] + cmd = 'VBoxManage closemedium disk {' + hdd['UUID'] + '} --delete' + results = self.hostExecute(cmd)[1] + # parse result 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100% + + self.changeStorageType(template_storage,'normal') + self.storageAttach('SecurityDVM') + self.startVM('SecurityDVM') + self.waitStartup('SecurityDVM') + self.guestExecute('SecurityDVM', 'sudo apt-get -y update' ) + self.guestExecute('SecurityDVM', 'sudo apt-get -y upgrade' ) + self.stopVM('SecurityDVM') + self.waitShutdown('SecurityDVM') + self.storageDetach('SecurityDVM') + self.changeStorageType(template_storage,'immutable') + self.storageAttach('SecurityDVM') + + #remove VM from the system. should be used on VMs returned by listSDVMs def removeVM(self, vm_name): print('removing ' + vm_name) cmd = 'VBoxManage unregistervm ' + vm_name + ' --delete' - print self.execute(cmd) + print self.hostExecute(cmd) machineFolder = self.getDefaultMachineFolder() cmd = self.cygwin_path + 'bash.exe --login -c \"rm -rf ' + machineFolder + '\\' + vm_name + '*\"' - print self.execute(cmd) + print self.hostExecute(cmd) # start VM def startVM(self, vm_name): print('starting ' + vm_name) cmd = 'VBoxManage startvm ' + vm_name + ' --type headless' - result = self.execute(cmd) + result = self.hostExecute(cmd) while not string.find(str(result), 'successfully started',): print "Failed to start SDVM: ", vm_name, " retrying" time.sleep(1) - result = self.execute(cmd) + result = self.hostExecute(cmd) return result[0] - - # stop VM + + # return wether VM is running or not + def isVMRunning(self, vm_name): + return vm_name in self.listRunningVMS() + + # stop VM def stopVM(self, vm_name): print('stopping ' + vm_name) + cmd = 'sudo shutdown -h now' + self.guestExecute('SecurityDVM', cmd) + + # poweroff VM + def poweroffVM(self, vm_name): + if not self.isVMRunning(vm_name): + return + print('powering off ' + vm_name) cmd = 'VBoxManage controlvm ' + vm_name + ' poweroff' - self.execute(cmd) + self.hostExecute(cmd) # return the hostOnly IP for a running guest def getHostOnlyIP(self, vm_name): print('gettting hostOnly IP address ' + vm_name) cmd = 'VBoxManage guestproperty get ' + vm_name + ' /VirtualBox/GuestInfo/Net/0/V4/IP' - result = self.execute(cmd) + result = self.hostExecute(cmd) if result=='': return None result = result[1] @@ -261,14 +341,14 @@ # attach removable storage device to VM by provision of filter def attachRSD(self, vm_name, rsd_filter): cmd = 'VBoxManage usbfilter add 0 --target ' + vm_name + ' --name OpenSecurityRSD --vendorid ' + rsd_filter.vendorid + ' --productid ' + rsd_filter.productid + ' --revision ' + rsd_filter.revision - print self.execute(cmd) + print self.hostExecute(cmd) # return the description set for an existing VM def getVMInfo(self, vm_name): cmd = 'VBoxManage showvminfo ' + vm_name + ' --machinereadable' - results = self.execute(cmd)[1] - props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split('=', 1) for line in results.splitlines())) + results = self.hostExecute(cmd)[1] + props = dict((k.strip().strip('"'),v.strip().strip('"')) for k,v in (line.split('=', 1) for line in results.splitlines())) return props # return the configured USB filter for an existing VM @@ -284,31 +364,40 @@ #generates ISO containing authorized_keys for use with guest VM def genCertificateISO(self, vm_name): machineFolder = self.getDefaultMachineFolder() + machineFolder = self.cygwinPath(machineFolder) + # remove .ssh folder if exists + cmd = self.cygwin_path+'bash.exe --login -c \"rm -rf \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"' + self.hostExecute(cmd) + # remove .ssh folder if exists + cmd = self.cygwin_path+'bash.exe --login -c \"rm -rf \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"\"' + self.hostExecute(cmd) # create .ssh folder in vm_name - cmd = self.cygwin_path+'bash.exe --login -c \"mkdir -p \\\"' + machineFolder + '\\' + vm_name + '\\.ssh\\\"\"' - self.execute(cmd) + cmd = self.cygwin_path+'bash.exe --login -c \"mkdir -p \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"' + self.hostExecute(cmd) # generate dvm_key pair in vm_name / .ssh - cmd = self.cygwin_path+'bash.exe --login -c \"ssh-keygen -q -t rsa -N \\"\\" -C \\\"' + vm_name + '\\\" -f \\\"' + machineFolder + '\\' + vm_name + '\\.ssh\\dvm_key\\\"\"' #'echo -e "y\\n" |', - self.execute(cmd) - # set permissions for keys - #TODO: test without chmod - cmd = self.cygwin_path+'bash.exe --login -c \"chmod 500 \\\"' + machineFolder + '\\' + vm_name + '\\.ssh\\*\\\"\"' - self.execute(cmd) + cmd = self.cygwin_path+'bash.exe --login -c \"ssh-keygen -q -t rsa -N \\"\\" -C \\\"' + vm_name + '\\\" -f \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\"\"' #'echo -e "y\\n" |', + self.hostExecute(cmd) # move out private key - cmd = self.cygwin_path+'bash.exe --login -c \"mv \\\"' + machineFolder + '\\' + vm_name + '\\.ssh\\dvm_key\\\" \\\"' + machineFolder + '\\' + vm_name + '\\\"' - self.execute(cmd) + cmd = self.cygwin_path+'bash.exe --login -c \"mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\" \\\"' + machineFolder + '/' + vm_name + '\\\"' + self.hostExecute(cmd) + # set permissions for private key + cmd = self.cygwin_path+'bash.exe --login -c \"chmod 500 \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"\"' + self.hostExecute(cmd) # rename public key to authorized_keys - cmd = self.cygwin_path+'bash.exe --login -c \"mv \\\"' + machineFolder + '\\' + vm_name + '\\.ssh\\dvm_key.pub\\\" \\\"' + machineFolder + '\\' + vm_name + '\\.ssh\\authorized_keys\\\"' - self.execute(cmd) + cmd = self.cygwin_path+'bash.exe --login -c \"mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key.pub\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"' + self.hostExecute(cmd) + # set permissions for authorized_keys + cmd = self.cygwin_path+'bash.exe --login -c \"chmod 500 \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"\"' + self.hostExecute(cmd) # generate iso image with .ssh/authorized keys - cmd = self.cygwin_path+'bash.exe --login -c \"/usr/bin/genisoimage -J -R -o \\\"' + machineFolder + '\\' + vm_name + '\\'+ vm_name + '.iso\\\" \\\"' + machineFolder + '\\' + vm_name + '\\.ssh\\\"\"' - self.execute(cmd) + cmd = self.cygwin_path+'bash.exe --login -c \"/usr/bin/genisoimage -J -R -o \\\"' + machineFolder + '/' + vm_name + '/'+ vm_name + '.iso\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"' + self.hostExecute(cmd) # attaches generated ssh public cert to guest vm def attachCertificateISO(self, vm_name): machineFolder = self.getDefaultMachineFolder() - cmd = 'vboxmanage storageattach ' + vm_name + ' --storagectl contr1 --port 1 --device 0 --type dvddrive --mtype readonly --medium \"' + machineFolder + '\\' + vm_name + '\\'+ vm_name + '.iso\"' - result = self.execute(cmd) + cmd = 'vboxmanage storageattach ' + vm_name + ' --storagectl SATA --port 1 --device 0 --type dvddrive --mtype readonly --medium \"' + machineFolder + '\\' + vm_name + '\\'+ vm_name + '.iso\"' + result = self.hostExecute(cmd) return result handleDeviceChangeLock = threading.Lock() @@ -348,6 +437,23 @@ VMManager.handleDeviceChangeLock.release() return new_ip + # wait for machine to come up + def waitStartup(self, vm_name): + new_ip = None + while new_ip == None: + time.sleep(1) + new_ip = self.getHostOnlyIP(vm_name) + while new_ip not in self.startNotifications: + time.sleep(1) + return + + # wait for machine to shutdown + def waitShutdown(self, vm_name): + while vm_name in self.listRunningVMS(): + time.sleep(1) + return + + # handles browsing request def handleBrowsingRequest(self): if VMManager.handleDeviceChangeLock.acquire(True): new_ip = None @@ -356,12 +462,7 @@ self.genCertificateISO(new_sdvm) self.attachCertificateISO(new_sdvm) self.startVM(new_sdvm) - # wait for machine to come up - while new_ip == None: - time.sleep(1) - new_ip = self.getHostOnlyIP(new_sdvm) - while new_ip not in self.startNotifications: - time.sleep(1) + self.waitStartup(new_sdvm) if new_ip != None: self.mapNetworkDrive('g:', '\\\\' + new_ip + '\\Download', None, None) #TODO: cleanup notifications somwhere else (eg. machine shutdown) @@ -369,17 +470,44 @@ VMManager.handleDeviceChangeLock.release() return new_sdvm + def cygwinPath(self, path): + # TODO: test if env ist cygwin + cmd = self.cygwin_path + 'bash.exe --login -c \"cygpath -u \\\"' + path + '\\\"\"' + return self.hostExecute(cmd)[1].rstrip('\n') + + #executes command on host system + def hostExecute(self, cmd, wait_return=True ): + if DEBUG: + print('trying to launch: ' + cmd) + process = Popen(cmd, stdout=PIPE, stderr=PIPE) #shell = True + if DEBUG: + print('launched: ' + cmd) + if not wait_return: + return [0, 'working in background', ''] + result = process.wait() + res_stdout = process.stdout.read(); + res_stderr = process.stderr.read(); + if DEBUG: + if res_stdout != "": + print res_stdout + if res_stderr != "": + print res_stderr + if result !=0: + raise VMManagerException(res_stderr) + return result, res_stdout, res_stderr + # executes command over ssh on guest vm - def sshGuestExecute(self, vm_name, prog, user_name='osecuser'): + def guestExecute(self, vm_name, prog, user_name='osecuser'): # get vm ip address = self.getHostOnlyIP(vm_name) machineFolder = self.getDefaultMachineFolder() - # run command - cmd = self.cygwin_path+'bash.exe --login -c \"ssh -i \\\"' + machineFolder + '\\' + vm_name + '\\dvm_key\\\" ' + user_name + '@' + address + ' ' + prog + '\"' - return self.execute(cmd) + machineFolder = self.cygwinPath(machineFolder) + # run command //mintty.exe -e + cmd = self.cygwin_path + 'bash.exe --login -c \"/usr/bin/ssh -v -i \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\" ' + user_name + '@' + address + ' ' + prog + '\"' + return self.hostExecute(cmd) # executes command over ssh on guest vm with X forwarding - def sshGuestX11Execute(self, vm_name, prog, user_name='osecuser'): + def guestExecuteX11(self, vm_name, prog, user_name='osecuser'): #TODO: verify if X server is running on user account #TODO: set DISPLAY accordingly address = self.getHostOnlyIP(vm_name) @@ -447,6 +575,7 @@ return -1 return 1 + if __name__ == '__main__': man = VMManager.getInstance() #man.removeVM('SecurityDVM0') @@ -463,9 +592,22 @@ #man.attachCertificateISO(new_vm) #man.attachCertificateISO(vm_name) - #man.sshGuestExecute(vm_name, "ls") - man.sshGuestX11Execute('SecurityDVM1', '/usr/bin/iceweasel') - time.sleep(60) + #man.guestExecute(vm_name, "ls") + #man.sshGuestX11Execute('SecurityDVM1', '/usr/bin/iceweasel') + #time.sleep(60) + #print man.cygwinPath("C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\.ssh\*") + #man.genCertificateISO('SecurityDVM') + #man.attachCertificateISO('SecurityDVM') + #man.isStorageAttached('SecurityDVM') + man.guestExecute('SecurityDVM', 'sudo apt-get -y update') + #man.guestExecute('SecurityDVM', 'sudo apt-get -y upgrade' ) + + #man.stopVM('SecurityDVM') + #man.storageDetach('SecurityDVM') + #man.changeStorageType('C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\SecurityDVM.vmdk','immutable') + #man.storageAttach('SecurityDVM') + + #cmd = "c:\\cygwin64\\bin\\bash.exe --login -c \"/bin/ls\"" #man.execute(cmd) \ No newline at end of file