1.1 --- a/OpenSecurity/bin/vmmanager.pyw Thu Jun 12 14:08:36 2014 +0200
1.2 +++ b/OpenSecurity/bin/vmmanager.pyw Thu Jul 17 10:20:10 2014 +0100
1.3 @@ -1,8 +1,37 @@
1.4 -'''
1.5 -Created on Nov 19, 2013
1.6 +#!/bin/env python
1.7 +# -*- coding: utf-8 -*-
1.8
1.9 -@author: BarthaM
1.10 -'''
1.11 +# ------------------------------------------------------------
1.12 +# opensecurityd
1.13 +#
1.14 +# the opensecurityd as RESTful server
1.15 +#
1.16 +# Autor: Mihai Bartha, <mihai.bartha@ait.ac.at>
1.17 +#
1.18 +# Copyright (C) 2013 AIT Austrian Institute of Technology
1.19 +# AIT Austrian Institute of Technology GmbH
1.20 +# Donau-City-Strasse 1 | 1220 Vienna | Austria
1.21 +# http://www.ait.ac.at
1.22 +#
1.23 +# This program is free software; you can redistribute it and/or
1.24 +# modify it under the terms of the GNU General Public License
1.25 +# as published by the Free Software Foundation version 2.
1.26 +#
1.27 +# This program is distributed in the hope that it will be useful,
1.28 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
1.29 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.30 +# GNU General Public License for more details.
1.31 +#
1.32 +# You should have received a copy of the GNU General Public License
1.33 +# along with this program; if not, write to the Free Software
1.34 +# Foundation, Inc., 51 Franklin Street, Fifth Floor,
1.35 +# Boston, MA 02110-1301, USA.
1.36 +# ------------------------------------------------------------
1.37 +
1.38 +
1.39 +# ------------------------------------------------------------
1.40 +# imports
1.41 +
1.42 import os
1.43 import os.path
1.44 from subprocess import Popen, PIPE, call, STARTUPINFO, _subprocess
1.45 @@ -27,6 +56,7 @@
1.46 import win32wnet
1.47 import urllib
1.48 import urllib2
1.49 +import unittest
1.50 DEBUG = True
1.51
1.52
1.53 @@ -64,7 +94,14 @@
1.54
1.55 #def __getitem__(self, item):
1.56 # return self.coords[item]
1.57 -
1.58 +def once(theClass):
1.59 + theClass.systemProperties = theClass.getSystemProperties()
1.60 + theClass.machineFolder = theClass.systemProperties["Default machine folder"]
1.61 + theClass.hostonlyIFs = theClass.getHostOnlyIFs()
1.62 + theClass.blacklistedRSD = theClass.loadRSDBlacklist()
1.63 + return theClass
1.64 +
1.65 +@once
1.66 class VMManager(object):
1.67 vmRootName = "SecurityDVM"
1.68 systemProperties = None
1.69 @@ -78,14 +115,9 @@
1.70
1.71
1.72 def __init__(self):
1.73 - self.systemProperties = self.getSystemProperties()
1.74 - self.machineFolder = self.systemProperties["Default machine folder"]
1.75 - self.hostonlyIFs = self.getHostOnlyIFs()
1.76 - VMManager.blacklistedRSD = self.loadRSDBlacklist()
1.77 # only proceed if we have a working background environment
1.78 if self.backend_ok():
1.79 self.cleanup()
1.80 - self.start()
1.81 else:
1.82 logger.critical(self.status_message)
1.83
1.84 @@ -116,24 +148,24 @@
1.85
1.86 # return the folder containing the guest VMs
1.87 def getMachineFolder(self):
1.88 - return self.machineFolder
1.89 + return VMManager.machineFolder
1.90
1.91 def backend_ok(self):
1.92
1.93 """check if the backend (VirtualBox) is sufficient for our task"""
1.94
1.95 # ensure we have our system props
1.96 - if self.systemProperties == None:
1.97 - self.systemProperties = self.getSystemProperties()
1.98 - if self.systemProperties == None:
1.99 + if VMManager.systemProperties == None:
1.100 + VMManager.systemProperties = self.getSystemProperties()
1.101 + if VMManager.systemProperties == None:
1.102 self.status_message = 'Failed to get backend system properties. Is Backend (VirtualBox?) installed?'
1.103 return False
1.104
1.105 # check for existing Extension pack
1.106 - if not 'Remote desktop ExtPack' in self.systemProperties:
1.107 + if not 'Remote desktop ExtPack' in VMManager.systemProperties:
1.108 self.status_message = 'No remote desktop extension pack found. Please install the "Oracle VM VirtualBox Extension Pack" from https://www.virtualbox.org/wiki/Downloads.'
1.109 return False
1.110 - if self.systemProperties['Remote desktop ExtPack'] == 'Oracle VM VirtualBox Extension Pack ':
1.111 + if VMManager.systemProperties['Remote desktop ExtPack'] == 'Oracle VM VirtualBox Extension Pack ':
1.112 self.status_message = 'Unsure if suitable extension pack is installed. Please install the "Oracle VM VirtualBox Extension Pack" from https://www.virtualbox.org/wiki/Downloads.'
1.113 return False
1.114
1.115 @@ -336,11 +368,11 @@
1.116 if self.isSDVMExisting(vm_name):
1.117 return
1.118 #remove eventually existing SDVM folder
1.119 - machineFolder = Cygwin.cygPath(self.machineFolder)
1.120 + machineFolder = Cygwin.cygPath(VMManager.machineFolder)
1.121 Cygwin.checkResult(Cygwin.bashExecute('/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '\\\"'))
1.122 hostonly_if = self.getHostOnlyIFs()
1.123 Cygwin.checkResult(Cygwin.vboxExecute('createvm --name ' + vm_name + ' --ostype Debian --register'))
1.124 - Cygwin.checkResult(Cygwin.vboxExecute('modifyvm ' + vm_name + ' --memory 512 --vram 10 --cpus 1 --usb on --usbehci on --nic1 hostonly --hostonlyadapter1 \"' + hostonly_if['Name'] + '\" --nic2 nat'))
1.125 + Cygwin.checkResult(Cygwin.vboxExecute('modifyvm ' + vm_name + ' --memory 768 --vram 10 --cpus 1 --usb on --usbehci on --nic1 hostonly --hostonlyadapter1 \"' + hostonly_if['Name'] + '\" --nic2 nat'))
1.126 Cygwin.checkResult(Cygwin.vboxExecute('storagectl ' + vm_name + ' --name SATA --add sata --portcount 2'))
1.127
1.128 #create new SecurityDVM with automatically generated name from template (thread safe)
1.129 @@ -354,7 +386,7 @@
1.130 def storageAttach(self, vm_name):
1.131 if self.isStorageAttached(vm_name):
1.132 self.storageDetach(vm_name)
1.133 - Cygwin.checkResult(Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium \"'+ self.machineFolder + '\SecurityDVM\SecurityDVM.vmdk\"'))
1.134 + Cygwin.checkResult(Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium \"'+ VMManager.machineFolder + '\SecurityDVM\SecurityDVM.vmdk\"'))
1.135
1.136 # return true if storage is attached
1.137 def isStorageAttached(self, vm_name):
1.138 @@ -379,19 +411,22 @@
1.139 # check for updates
1.140 self.genCertificateISO(self.vmRootName)
1.141 self.attachCertificateISO(self.vmRootName)
1.142 - imageUUID = self.getVMInfo(self.vmRootName)["SATA-ImageUUID-0-0"] #TODO: // verify value
1.143 +
1.144 + #templateUUID = self.getVMInfo(self.vmRootName)["SATA-ImageUUID-0-0"] #TODO: // verify value
1.145 + templateUUID = self.getTemplateUUID()
1.146 +
1.147 self.storageDetach(self.vmRootName)
1.148 - self.removeSnapshots(imageUUID)
1.149 + self.removeSnapshots(templateUUID)
1.150
1.151 - template_storage = self.machineFolder + '\\' + self.vmRootName + '\\' + self.vmRootName + '.vmdk'
1.152 + template_storage = VMManager.machineFolder + '\\' + self.vmRootName + '\\' + self.vmRootName + '.vmdk'
1.153 #TODO:// modify to take vm name as argument
1.154 self.changeStorageType(template_storage,'normal')
1.155 self.storageAttach(self.vmRootName)
1.156 self.startVM(self.vmRootName)
1.157 - self.waitStartup(self.vmRootName)
1.158 + self.waitStartup(self.vmRootName, timeout_ms = 30000)
1.159
1.160 tmp_ip = self.getHostOnlyIP(self.vmRootName)
1.161 - tmp_machine_folder = Cygwin.cygPath(self.machineFolder)
1.162 + tmp_machine_folder = Cygwin.cygPath(VMManager.machineFolder)
1.163 Cygwin.checkResult(Cygwin.sshExecute('"sudo apt-get -y update"', tmp_ip, 'osecuser', tmp_machine_folder + '/' + self.vmRootName + '/dvm_key'))
1.164 Cygwin.checkResult(Cygwin.sshExecute('"sudo apt-get -y upgrade"', tmp_ip, 'osecuser', tmp_machine_folder + '/' + self.vmRootName + '/dvm_key'))
1.165
1.166 @@ -403,17 +438,19 @@
1.167 self.startVM(self.vmRootName)
1.168 self.waitStartup(self.vmRootName)
1.169
1.170 - self.hibernateVM(self.vmRootName)
1.171 + #self.hibernateVM(self.vmRootName)
1.172 + self.stopVM(self.vmRootName)
1.173 self.waitShutdown(self.vmRootName)
1.174 self.storageDetach(self.vmRootName)
1.175 self.changeStorageType(template_storage,'immutable')
1.176 self.storageAttach(self.vmRootName)
1.177
1.178 - self.start()
1.179 + #self.start()
1.180
1.181 #"SATA-0-0"="C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\Snapshots\{d0af827d-f13a-49be-8ac1-df20b13bda83}.vmdk"
1.182 - #"SATA-ImageUUID-0-0"="d0af827d-f13a-49be-8ac1-df20b13bda83"
1.183 - def getDiskImages(self):
1.184 + #"SATA-ImageUUID-0-0"="d0af827d-f13a-49be-8ac1-df20b13bda83"
1.185 + @staticmethod
1.186 + def getDiskImages():
1.187 results = Cygwin.checkResult(Cygwin.vboxExecute('list hdds'))[1]
1.188 results = results.replace('Parent UUID', 'Parent')
1.189 items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
1.190 @@ -428,9 +465,10 @@
1.191 snaps[props['UUID']] = props
1.192 return snaps
1.193
1.194 - def getTemplateUUID(self):
1.195 - images = self.getDiskImages()
1.196 - template_storage = self.machineFolder + '\\' + self.vmRootName + '/' +self.vmRootName + '.vmdk'
1.197 + @staticmethod
1.198 + def getTemplateUUID():
1.199 + images = VMManager.getDiskImages()
1.200 + template_storage = VMManager.machineFolder + '\\' + VMManager.vmRootName + '\\' + VMManager.vmRootName + '.vmdk'
1.201 # find template uuid
1.202 template_uuid = None
1.203 for hdd in images.values():
1.204 @@ -462,18 +500,19 @@
1.205 self.removeVMFolder(vm_name)
1.206
1.207 def removeVMFolder(self, vm_name):
1.208 - machineFolder = Cygwin.cygPath(self.machineFolder)
1.209 + machineFolder = Cygwin.cygPath(VMManager.machineFolder)
1.210 Cygwin.checkResult(Cygwin.bashExecute('/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '\\\"'))
1.211
1.212 # start VM
1.213 def startVM(self, vm_name):
1.214 logger.info('Starting ' + vm_name)
1.215 - result = Cygwin.checkResult(Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless' ))
1.216 + #TODO: modify to use Cygwin.checkResult() of make it retry 3 times
1.217 + result = Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless' )
1.218 while 'successfully started' not in result[1]:
1.219 logger.error("Failed to start SDVM: " + vm_name + " retrying")
1.220 logger.error("Command returned:\n" + result[2])
1.221 time.sleep(1)
1.222 - result = Cygwin.checkResult(Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless'))
1.223 + result = Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless')
1.224 return result[0]
1.225
1.226 # return wether VM is running or not
1.227 @@ -483,12 +522,12 @@
1.228 # stop VM
1.229 def stopVM(self, vm_name):
1.230 logger.info('Sending shutdown signal to ' + vm_name)
1.231 - Cygwin.checkResult(Cygwin.sshExecute( '"sudo shutdown -h now"', self.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key' ))
1.232 + Cygwin.checkResult(Cygwin.sshExecute( '"sudo shutdown -h now"', self.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(VMManager.machineFolder) + '/' + vm_name + '/dvm_key' ))
1.233
1.234 # stop VM
1.235 def hibernateVM(self, vm_name):
1.236 logger.info('Sending hibernate-disk signal to ' + vm_name)
1.237 - Cygwin.checkResult(Cygwin.sshBackgroundExecute( '"sudo hibernate-disk"', self.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key', wait_return=False))
1.238 + Cygwin.checkResult(Cygwin.sshBackgroundExecute( '"sudo hibernate-disk"', self.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(VMManager.machineFolder) + '/' + vm_name + '/dvm_key', wait_return=False))
1.239
1.240 # poweroff VM
1.241 def poweroffVM(self, vm_name):
1.242 @@ -502,7 +541,7 @@
1.243 if vm_name == None:
1.244 logger.info('Getting hostOnly IP address for Host')
1.245 #TODO:// optimise to store on init local variable and return that value (avoid calling list hostonlyifs)
1.246 - return self.hostonlyIFs['IPAddress']
1.247 + return VMManager.hostonlyIFs['IPAddress']
1.248 else:
1.249 logger.info('Getting hostOnly IP address ' + vm_name)
1.250 result = Cygwin.checkResult(Cygwin.vboxExecute('guestproperty get ' + vm_name + ' /VirtualBox/GuestInfo/Net/0/V4/IP'))
1.251 @@ -521,7 +560,7 @@
1.252
1.253 #generates ISO containing authorized_keys for use with guest VM
1.254 def genCertificateISO(self, vm_name):
1.255 - machineFolder = Cygwin.cygPath(self.machineFolder)
1.256 + machineFolder = Cygwin.cygPath(VMManager.machineFolder)
1.257 # remove .ssh folder if exists
1.258 Cygwin.checkResult(Cygwin.bashExecute('/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"'))
1.259 # remove .ssh folder if exists
1.260 @@ -543,12 +582,12 @@
1.261
1.262 # attaches generated ssh public cert to guest vm
1.263 def attachCertificateISO(self, vm_name):
1.264 - result = Cygwin.checkResult(Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 1 --device 0 --type dvddrive --mtype readonly --medium \"' + self.machineFolder + '\\' + vm_name + '\\'+ vm_name + '.iso\"'))
1.265 + result = Cygwin.checkResult(Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 1 --device 0 --type dvddrive --mtype readonly --medium \"' + VMManager.machineFolder + '\\' + vm_name + '\\'+ vm_name + '.iso\"'))
1.266 return result
1.267
1.268 # wait for machine to come up
1.269 - def waitStartup(self, vm_name, timeout_ms = 30000):
1.270 - Cygwin.checkResult(Cygwin.vboxExecute('guestproperty wait ' + vm_name + ' SDVMStarted --timeout ' + str(timeout_ms) + ' --fail-on-timeout'))
1.271 + def waitStartup(self, vm_name, timeout_ms = 1000):
1.272 + Cygwin.checkResult(Cygwin.vboxExecute('guestproperty wait ' + vm_name + ' SDVMStarted --timeout ' + str(timeout_ms) + ' --fail-on-timeout', try_count = 60))
1.273 return self.getHostOnlyIP(vm_name)
1.274
1.275 # wait for machine to shutdown
1.276 @@ -681,7 +720,6 @@
1.277 command = '-r -o StrictHostKeyChecking=no -i "' + certificate + '" "' + src + '" "osecuser@' + self.browsingManager.ip_addr + ':' + dest + '"'
1.278 return Cygwin.execute(Cygwin.cygwin_scp, command, wait_return=True, window=False)
1.279
1.280 -
1.281 #handles browsing session creation
1.282 class BrowsingHandler(threading.Thread):
1.283 vmm = None
1.284 @@ -748,8 +786,10 @@
1.285 self.vmm.storageAttach(self.vm_name)
1.286 self.vmm.genCertificateISO(self.vm_name)
1.287 self.vmm.attachCertificateISO(self.vm_name)
1.288 +
1.289 self.vmm.startVM(self.vm_name)
1.290 - self.ip_addr = self.vmm.waitStartup(self.vm_name)
1.291 +
1.292 + self.ip_addr = self.vmm.waitStartup(self.vm_name, timeout_ms=30000)
1.293 if self.ip_addr == None:
1.294 logger.error("Failed to get ip address")
1.295 continue
1.296 @@ -797,8 +837,12 @@
1.297 self.started.set()
1.298 logger.info("Browsing SDVM running.")
1.299 self.restart.wait()
1.300 + except OpenSecurityException, e:
1.301 + logger.error(''.join(e))
1.302 except:
1.303 + logger.error("Unexpected error: " + sys.exc_info()[0])
1.304 logger.error("BrowsingHandler failed. Cleaning up")
1.305 + #self.running= False
1.306
1.307 class DeviceHandler(threading.Thread):
1.308 vmm = None
1.309 @@ -881,82 +925,3 @@
1.310 continue
1.311
1.312 self.existingRSDs = tmp_rsds
1.313 -
1.314 -
1.315 -if __name__ == '__main__':
1.316 - #man = VMManager.getInstance()
1.317 - #man.listVM()
1.318 - #print man.getConnectedRSDs()
1.319 - #print man.getNetworkDrives()
1.320 - #man.genNetworkDrive()
1.321 - #drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
1.322 - #print list(itertools.compress(string.ascii_uppercase, map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
1.323 - #print list(map(chr, range(68, 91)))
1.324 - #print Cygwin.getRegEntry('SYSTEM\CurrentControlSet\Enum\USB', 'VID_1058&PID_0704')[0]
1.325 - #devices = VMManager.getConnectedRSDS()
1.326 - #print devices
1.327 -
1.328 - drives = VMManager.getLogicalDrives()
1.329 - print drives
1.330 - print VMManager.getDriveType("E")
1.331 - print VMManager.getVolumeInfo("E")
1.332 - print VMManager.getNetworkPath("E")
1.333 -
1.334 - #vmm.backupFile()
1.335 - #for device in devices.values():
1.336 - # #print device
1.337 - # if VMManager.isMassStorageDevice(device):
1.338 - # print device
1.339 -
1.340 -
1.341 -
1.342 - #time.sleep(-1)
1.343 - #man.listVM()
1.344 - #man.listVM()
1.345 - #man.listVM()
1.346 - #man.listVM()
1.347 - #man.genCertificateISO('SecurityDVM0')
1.348 - #man.guestExecute('SecurityDVM0', '/bin/ls -la')
1.349 - #logger = setupLogger('VMManager')
1.350 - #c = Cygwin()
1.351 -
1.352 - #man.sshExecute('/bin/ls -la', 'SecurityDVM0')
1.353 - #man.sshExecuteX11('/usr/bin/iceweasel', 'SecurityDVM0')
1.354 - #man.removeVM('SecurityDVM0')
1.355 - #man.netUse('192.168.56.134', 'USB\\')
1.356 - #ip = '192.168.56.139'
1.357 -
1.358 - #man.cygwin_path = 'c:\\cygwin64\\bin\\'
1.359 - #man.handleDeviceChange()
1.360 - #print man.listSDVM()
1.361 - #man.configureHostNetworking()
1.362 - #new_vm = man.generateSDVMName()
1.363 - #man.createVM(new_vm)
1.364 -
1.365 - #print Cygwin.cmd()
1.366 - #man.isAvailable('c:')
1.367 - #ip = man.getHostOnlyIP('SecurityDVM0')
1.368 - #man.mapNetworkDrive('h:', '\\\\' + ip + '\Download', None, None)
1.369 -
1.370 - #man.genCertificateISO(new_vm)
1.371 - #man.attachCertificateISO(new_vm)
1.372 -
1.373 - #man.attachCertificateISO(vm_name)
1.374 - #man.guestExecute(vm_name, "ls")
1.375 - #man.sshGuestX11Execute('SecurityDVM1', '/usr/bin/iceweasel')
1.376 - #time.sleep(60)
1.377 - #print man.cygwinPath("C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\.ssh\*")
1.378 - #man.genCertificateISO('SecurityDVM')
1.379 - #man.attachCertificateISO('SecurityDVM')
1.380 - #man.isStorageAttached('SecurityDVM')
1.381 - #man.guestExecute('SecurityDVM', 'sudo apt-get -y update')
1.382 - #man.guestExecute('SecurityDVM', 'sudo apt-get -y upgrade' )
1.383 -
1.384 - #man.stopVM('SecurityDVM')
1.385 - #man.storageDetach('SecurityDVM')
1.386 - #man.changeStorageType('C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\SecurityDVM.vmdk','immutable')
1.387 - #man.storageAttach('SecurityDVM')
1.388 -
1.389 -
1.390 - #cmd = "c:\\cygwin64\\bin\\bash.exe --login -c \"/bin/ls\""
1.391 - #man.execute(cmd)