1.1 --- a/OpenSecurity/bin/vmmanager.pyw Fri Aug 29 10:56:26 2014 +0100
1.2 +++ b/OpenSecurity/bin/vmmanager.pyw Fri Sep 05 12:28:30 2014 +0100
1.3 @@ -47,7 +47,7 @@
1.4 import shutil
1.5 import stat
1.6 import tempfile
1.7 -from opensecurity_util import logger, setupLogger, OpenSecurityException, showTrayMessage
1.8 +from opensecurity_util import logger, import_logger, setupLogger, OpenSecurityException, showTrayMessage
1.9 import ctypes
1.10 import itertools
1.11 import win32api
1.12 @@ -99,6 +99,7 @@
1.13 theClass.machineFolder = theClass.systemProperties["Default machine folder"]
1.14 #theClass.hostonlyIF = theClass.getHostOnlyIFs()["VirtualBox Host-Only Ethernet Adapter"]
1.15 theClass.blacklistedRSD = theClass.loadRSDBlacklist()
1.16 + theClass.templateImage = theClass.machineFolder + '\\' + theClass.vmRootName + '\\' + theClass.vmRootName + '.vmdk'
1.17 return theClass
1.18
1.19 @once
1.20 @@ -112,6 +113,9 @@
1.21 browsingManager = None
1.22 blacklistedRSD = None
1.23 status_message = 'Starting up...'
1.24 + templateImage = None
1.25 + importHandler = None
1.26 + updateHandler = None
1.27
1.28 def __init__(self):
1.29 # only proceed if we have a working background environment
1.30 @@ -203,7 +207,7 @@
1.31
1.32 def template_installed(self):
1.33 """ check if we do have our root VMs installed """
1.34 - vms = self.listVM()
1.35 + vms = self.listVMS()
1.36 if not self.vmRootName in vms:
1.37 self.status_message = 'Unable to locate root SecurityDVM. Please download and setup the initial image.'
1.38 return False
1.39 @@ -248,7 +252,16 @@
1.40 self.browsingManager = None
1.41 Cygwin.allowExec()
1.42
1.43 - def start(self):
1.44 + def start(self, force = False):
1.45 + if not force:
1.46 + if self.importHandler and self.importHandler.isAlive():
1.47 + logger.info("Initial update running canceling start.")
1.48 + return
1.49 +
1.50 + if self.updateHandler and self.updateHandler.isAlive():
1.51 + logger.info("Update running canceling start.")
1.52 + return
1.53 +
1.54 self.stop()
1.55 Cygwin.allowExec()
1.56 if self.backend_ok() and self.template_installed():
1.57 @@ -272,7 +285,7 @@
1.58 self.removeVM(vm)
1.59
1.60 # list all existing VMs registered with VBox
1.61 - def listVM(self):
1.62 + def listVMS(self):
1.63 result = Cygwin.vboxExecute('list vms')[1]
1.64 vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines()))
1.65 return vms
1.66 @@ -285,7 +298,7 @@
1.67
1.68 # list existing SDVMs
1.69 def listSDVM(self):
1.70 - vms = self.listVM()
1.71 + vms = self.listVMS()
1.72 svdms = []
1.73 for vm in vms:
1.74 if vm.startswith(self.vmRootName) and vm != self.vmRootName:
1.75 @@ -294,7 +307,7 @@
1.76
1.77 # generate valid (not already existing SDVM name). necessary for creating a new VM
1.78 def genSDVMName(self):
1.79 - vms = self.listVM()
1.80 + vms = self.listVMS()
1.81 for i in range(0,999):
1.82 if(not self.vmRootName+str(i) in vms):
1.83 return self.vmRootName+str(i)
1.84 @@ -378,15 +391,6 @@
1.85 return rsds
1.86
1.87
1.88 - #def getAttachedRSD(self, vm_name):
1.89 - # props = self.getVMInfo(vm_name)
1.90 - # keys = set(['USBFilterVendorId1', 'USBFilterProductId1', 'USBFilterRevision1', 'USBFilterSerialNumber1'])
1.91 - # keyset = set(props.keys())
1.92 - # usb_filter = None
1.93 - # if keyset.issuperset(keys):
1.94 - # usb_filter = USBFilter(props['USBFilterVendorId1'], props['USBFilterProductId1'], props['USBFilterRevision1'])
1.95 - # return usb_filter
1.96 -
1.97 # return the attached USB device as usb descriptor for an existing VM
1.98 def getAttachedRSD(self, vm_name):
1.99 props = self.getVMInfo(vm_name)
1.100 @@ -452,73 +456,48 @@
1.101 self.createVM(vm_name)
1.102 return vm_name
1.103
1.104 + #VMManager.machineFolder + '\SecurityDVM\SecurityDVM.vmdk
1.105 # attach storage image to controller
1.106 - def attachStorage(self, vm_name):
1.107 - if self.isStorageAttached(vm_name):
1.108 - self.detachStorage(vm_name)
1.109 - Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium \"'+ VMManager.machineFolder + '\SecurityDVM\SecurityDVM.vmdk\"')
1.110 + def attachVDisk(self, vm_name, vdisk_controller, vdisk_port, vdisk_device, vdisk_image):
1.111 + if self.isVDiskAttached(vm_name, vdisk_controller, vdisk_port, vdisk_device):
1.112 + self.detachVDisk(vm_name, vdisk_controller, vdisk_port, vdisk_device)
1.113 + Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl '+ vdisk_controller + ' --port ' + vdisk_port + ' --device ' + vdisk_device + ' --type hdd --medium "'+ vdisk_image + '"')
1.114
1.115 # return true if storage is attached
1.116 - def isStorageAttached(self, vm_name):
1.117 + def isVDiskAttached(self, vm_name, vdisk_controller, vdisk_port, vdisk_device):
1.118 info = self.getVMInfo(vm_name)
1.119 - return (info['SATA-0-0']!='none')
1.120 + return (info[vdisk_controller+'-'+vdisk_port+'-'+vdisk_device] != 'none')
1.121
1.122 # detach storage from controller
1.123 - def detachStorage(self, vm_name):
1.124 - if self.isStorageAttached(vm_name):
1.125 - Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium none')
1.126 + def detachVDisk(self, vm_name, vdisk_controller, vdisk_port, vdisk_device):
1.127 + if self.isVDiskAttached(vm_name, vdisk_controller, vdisk_port, vdisk_device):
1.128 + Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl ' + vdisk_controller + ' --port ' + vdisk_port + ' --device ' + vdisk_device + ' --medium none')
1.129
1.130 - def changeStorageType(self, filename, storage_type):
1.131 - Cygwin.vboxExecute('modifyhd \"' + filename + '\" --type ' + storage_type)
1.132 -
1.133 - # list storage snaphots for VM
1.134 - def updateTemplate(self):
1.135 - self.stop()
1.136 - self.cleanup()
1.137 - self.poweroffVM(self.vmRootName)
1.138 - self.waitShutdown(self.vmRootName)
1.139 + # modify type of the vdisk_image
1.140 + def changeVDiskType(self, vdisk_image, storage_type):
1.141 + Cygwin.vboxExecute('modifyhd "' + vdisk_image + '" --type ' + storage_type)
1.142
1.143 - # check for updates
1.144 - self.genCertificate(self.vmRootName)
1.145 - self.attachCertificate(self.vmRootName)
1.146 + # grab VM storage controller, port and device for vdisk image name
1.147 + def getVDiskController(self, vm_name, image_name = '.vmdk'):
1.148 + vm_description = self.getVMInfo(vm_name)
1.149 + vdisk_controller = None
1.150 + for key, value in vm_description.iteritems():
1.151 + if image_name in value:
1.152 + vdisk_controller = key
1.153 + break
1.154 + return vdisk_controller
1.155 +
1.156 + # return attached vmdk image name containing image_name
1.157 + def getVDiskImage(self, vm_name, image_name = '.vmdk'):
1.158 + vmInfo = self.getVMInfo(vm_name)
1.159 + vdisk_image = None
1.160 + for value in vmInfo.values():
1.161 + if image_name in value:
1.162 + break
1.163 + return vdisk_image
1.164
1.165 - #templateUUID = self.getVMInfo(self.vmRootName)["SATA-ImageUUID-0-0"] #TODO: // verify value
1.166 - templateUUID = self.getTemplateUUID()
1.167 -
1.168 - self.detachStorage(self.vmRootName)
1.169 - self.removeSnapshots(templateUUID)
1.170 -
1.171 - template_storage = VMManager.machineFolder + '\\' + self.vmRootName + '\\' + self.vmRootName + '.vmdk'
1.172 - #TODO:// modify to take vm name as argument
1.173 - self.changeStorageType(template_storage,'normal')
1.174 - self.attachStorage(self.vmRootName)
1.175 - self.startVM(self.vmRootName)
1.176 - self.waitStartup(self.vmRootName)
1.177 -
1.178 - tmp_ip = self.getHostOnlyIP(self.vmRootName)
1.179 - tmp_machine_folder = Cygwin.cygPath(VMManager.machineFolder)
1.180 - Cygwin.sshExecute('"sudo apt-get -y update"', tmp_ip, 'osecuser', tmp_machine_folder + '/' + self.vmRootName + '/dvm_key')
1.181 - Cygwin.sshExecute('"sudo apt-get -y upgrade"', tmp_ip, 'osecuser', tmp_machine_folder + '/' + self.vmRootName + '/dvm_key')
1.182 -
1.183 - #check if reboot is required
1.184 - result = Cygwin.sshExecute('"if [ -f /var/run/reboot-required ]; then echo \\\"Yes\\\"; fi"', tmp_ip, 'osecuser', tmp_machine_folder + '/' + self.vmRootName + '/dvm_key')
1.185 - if "Yes" in result[1]:
1.186 - self.stopVM(self.vmRootName)
1.187 - self.waitShutdown(self.vmRootName)
1.188 - self.startVM(self.vmRootName)
1.189 - self.waitStartup(self.vmRootName)
1.190 -
1.191 - #self.hibernateVM(self.vmRootName)
1.192 - self.stopVM(self.vmRootName)
1.193 - self.waitShutdown(self.vmRootName)
1.194 - self.detachStorage(self.vmRootName)
1.195 - self.changeStorageType(template_storage,'immutable')
1.196 - self.attachStorage(self.vmRootName)
1.197 -
1.198 - #"SATA-0-0"="C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\Snapshots\{d0af827d-f13a-49be-8ac1-df20b13bda83}.vmdk"
1.199 - #"SATA-ImageUUID-0-0"="d0af827d-f13a-49be-8ac1-df20b13bda83"
1.200 @staticmethod
1.201 - def getDiskImages():
1.202 + def getVDiskImages():
1.203 results = Cygwin.vboxExecute('list hdds')[1]
1.204 results = results.replace('Parent UUID', 'Parent')
1.205 items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
1.206 @@ -534,19 +513,18 @@
1.207 return snaps
1.208
1.209 @staticmethod
1.210 - def getTemplateUUID():
1.211 - images = VMManager.getDiskImages()
1.212 - template_storage = VMManager.machineFolder + '\\' + VMManager.vmRootName + '\\' + VMManager.vmRootName + '.vmdk'
1.213 + def getVDiskUUID(vdisk_image):
1.214 + images = VMManager.getVDiskImages()
1.215 # find template uuid
1.216 template_uuid = None
1.217 for hdd in images.values():
1.218 - if hdd['Location'] == template_storage:
1.219 + if hdd['Location'] == vdisk_image:
1.220 template_uuid = hdd['UUID']
1.221 break
1.222 return template_uuid
1.223 -
1.224 +
1.225 def removeSnapshots(self, imageUUID):
1.226 - snaps = self.getDiskImages()
1.227 + snaps = self.getVDiskImages()
1.228 # remove snapshots
1.229 for hdd in snaps.values():
1.230 if hdd['Parent'] == imageUUID:
1.231 @@ -561,15 +539,14 @@
1.232 #remove VM from the system. should be used on VMs returned by listSDVMs
1.233 def removeVM(self, vm_name):
1.234 logger.info('Removing ' + vm_name)
1.235 -
1.236 Cygwin.vboxExecute('unregistervm ' + vm_name + ' --delete')
1.237 - #TODO:// try to close medium if still existing
1.238 + #try to close medium if still existing
1.239 #Cygwin.vboxExecute('closemedium disk {' + hdd['UUID'] + '} --delete')
1.240 self.removeVMFolder(vm_name)
1.241
1.242 def removeVMFolder(self, vm_name):
1.243 machineFolder = Cygwin.cygPath(VMManager.machineFolder)
1.244 - Cygwin.bashExecute('/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '\\\"')
1.245 + Cygwin.bashExecute('/usr/bin/rm -rf \\\"' + machineFolder + '\\' + vm_name + '\\\"')
1.246
1.247 # start VM
1.248 def startVM(self, vm_name):
1.249 @@ -790,10 +767,9 @@
1.250
1.251 def getAppDataDir(self, sid):
1.252 key = win32api.RegOpenKey(win32con.HKEY_USERS, sid + '\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders')
1.253 - value, type = win32api.RegQueryValueEx(key, "AppData")
1.254 + value, _ = win32api.RegQueryValueEx(key, "AppData")
1.255 win32api.RegCloseKey(key)
1.256 return value
1.257 -
1.258 #key = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList' + '\\' + sid)
1.259 #value, type = win32api.RegQueryValueEx(key, "ProfileImagePath")
1.260 #print value
1.261 @@ -807,8 +783,177 @@
1.262 certificate = Cygwin.cygPath(self.getMachineFolder()) + '/' + self.browsingManager.vm_name + '/dvm_key'
1.263 #command = '-r -v -o StrictHostKeyChecking=no -i \"' + certificate + '\" \"' + src + '\" \"osecuser@' + self.browsingManager.ip_addr + ':' + dest + '\"'
1.264 command = '-r -o StrictHostKeyChecking=no -i "' + certificate + '" "' + src + '" "osecuser@' + self.browsingManager.ip_addr + ':' + dest + '"'
1.265 - return Cygwin.execute(Cygwin.cygwin_scp, command, wait_return=True, window=False)
1.266 + return Cygwin.execute(Cygwin.cygwin_scp, command, wait_return=True, window=False)
1.267 +
1.268 + #import initial template
1.269 + def importTemplate(self, image_path):
1.270 + import_logger.info('Stopping Opensecurity...')
1.271 + self.stop()
1.272 +
1.273 + import_logger.info('Cleaning up system in preparation for import...')
1.274 + self.cleanup()
1.275 +
1.276 + import_logger.info('Removing template SDVM...')
1.277 + # if template exists
1.278 + if self.vmRootName in self.listVMS():
1.279 + # shutdown template if running
1.280 + self.poweroffVM(self.vmRootName)
1.281 + # detach and remove VDisk
1.282 + tmplateUUID = self.getVDiskUUID(self.templateImage)
1.283 + if tmplateUUID != None:
1.284 + logger.debug('Found template VDisk uuid ' + tmplateUUID)
1.285 + controller = self.getVDiskController(self.vmRootName)
1.286 + if controller:
1.287 + controller = controller.split('-')
1.288 + self.detachVDisk(self.vmRootName, controller[0], controller[1], controller[2])
1.289 + self.removeSnapshots(tmplateUUID)
1.290 + self.removeImage(tmplateUUID)
1.291 + else:
1.292 + logger.info('Template uuid not found')
1.293 + # remove VM
1.294 + self.removeVM(self.vmRootName)
1.295 + # remove template VM folder
1.296 + self.removeVMFolder(self.vmRootName)
1.297 + import_logger.info('Cleanup finished...')
1.298 +
1.299 + import_logger.info('Checking privileges...')
1.300 + result = Cygwin.bashExecute('id -G')
1.301 + if '544' not in result[1]:
1.302 + import_logger.debug('Insufficient privileges.')
1.303 + import_logger.debug("Trying to continue...")
1.304 +
1.305 + # check OpenSecurity Initial VM Image
1.306 + import_logger.debug('Looking for VM image: ' + image_path)
1.307 + result = os.path.isfile(image_path)
1.308 +
1.309 + if not result:
1.310 + import_logger.debug('Warning: no OpenSecurity Initial Image found.')
1.311 + import_logger.debug('Please download using the OpenSecurity download tool.')
1.312 + raise OpenSecurityException('OpenSecurity Initial Image not found.')
1.313 + logger.debug('Initial VM image: ' + image_path + ' found')
1.314 +
1.315 + if not self.template_installed():
1.316 + import_logger.info('Importing SDVm template: ' + image_path)
1.317 + Cygwin.vboxExecute('import "' + image_path + '" --vsys 0 --vmname ' + VMManager.vmRootName + ' --unit 12 --disk "' + self.templateImage + '"')
1.318 + else:
1.319 + import_logger.info('Found ' + VMManager.vmRootName + ' already present in VBox reusing it.')
1.320 + import_logger.info('if you want a complete new import please remove the VM first.')
1.321 + import_logger.info('starting OpenSecurity service...')
1.322 + return
1.323
1.324 + # remove unnecessary IDE controller
1.325 + Cygwin.vboxExecute('storagectl ' + VMManager.vmRootName + ' --name IDE --remove')
1.326 +
1.327 + info = self.getVDiskController(VMManager.vmRootName, self.templateImage)
1.328 + if info:
1.329 + info = info.split('-')
1.330 + self.detachVDisk(VMManager.vmRootName, info[0], info[1], info[2])
1.331 +
1.332 + self.changeVDiskType(self.templateImage, 'immutable')
1.333 + self.attachVDisk(VMManager.vmRootName, info[0], info[1], info[2], self.templateImage)
1.334 + import_logger.info('Initial import finished.')
1.335 +
1.336 + # update template
1.337 + def updateTemplate(self):
1.338 + import_logger.debug('Stopping Opensecurity...')
1.339 + self.stop()
1.340 +
1.341 + import_logger.debug('Cleaning up system in preparation for update...')
1.342 + self.cleanup()
1.343 +
1.344 + import_logger.info('Cleanup finished...')
1.345 +
1.346 + # shutdown template if running
1.347 + self.poweroffVM(self.vmRootName)
1.348 +
1.349 + import_logger.info('Starting template VM...')
1.350 + # check for updates
1.351 + self.genCertificate(self.vmRootName)
1.352 + self.attachCertificate(self.vmRootName)
1.353 +
1.354 + import_logger.info('Removing snapshots...')
1.355 +
1.356 + self.detachVDisk(self.vmRootName, 'SATA', '0', '0')
1.357 + templateUUID = self.getVDiskUUID(self.templateImage)
1.358 + self.removeSnapshots(templateUUID)
1.359 +
1.360 + import_logger.info('Setting VDisk image to normal...')
1.361 + self.changeVDiskType(self.templateImage, 'normal')
1.362 + self.attachVDisk(self.vmRootName, 'SATA', '0', '0', self.templateImage)
1.363 +
1.364 + import_logger.info('Starting VM...')
1.365 + self.startVM(self.vmRootName)
1.366 + self.waitStartup(self.vmRootName)
1.367 +
1.368 + import_logger.info('Updating components...')
1.369 + tmp_ip = self.getHostOnlyIP(self.vmRootName)
1.370 + tmp_machine_folder = Cygwin.cygPath(VMManager.machineFolder)
1.371 + Cygwin.sshExecute('"sudo apt-get -y update"', tmp_ip, 'osecuser', tmp_machine_folder + '/' + self.vmRootName + '/dvm_key')
1.372 + Cygwin.sshExecute('"sudo apt-get -y upgrade"', tmp_ip, 'osecuser', tmp_machine_folder + '/' + self.vmRootName + '/dvm_key')
1.373 +
1.374 + import_logger.info('Restarting template VM...')
1.375 + #check if reboot is required
1.376 + result = Cygwin.sshExecute('"if [ -f /var/run/reboot-required ]; then echo \\\"Yes\\\"; fi"', tmp_ip, 'osecuser', tmp_machine_folder + '/' + self.vmRootName + '/dvm_key')
1.377 + if "Yes" in result[1]:
1.378 + self.stopVM(self.vmRootName)
1.379 + self.waitShutdown(self.vmRootName)
1.380 + self.startVM(self.vmRootName)
1.381 + self.waitStartup(self.vmRootName)
1.382 +
1.383 + import_logger.info('Stopping template VM...')
1.384 + self.stopVM(self.vmRootName)
1.385 + self.waitShutdown(self.vmRootName)
1.386 +
1.387 + import_logger.info('Setting VDisk image to immutable...')
1.388 + self.detachVDisk(self.vmRootName, 'SATA', '0', '0')
1.389 + self.changeVDiskType(self.templateImage, 'immutable')
1.390 + self.attachVDisk(self.vmRootName, 'SATA', '0', '0', self.templateImage)
1.391 +
1.392 + import_logger.info('Update template finished...')
1.393 +
1.394 + def startInitialImport(self):
1.395 + if self.importHandler and self.importHandler.isAlive():
1.396 + import_logger.info("Initial import already running.")
1.397 + return
1.398 + self.importHandler = InitialImportHandler(self)
1.399 + self.importHandler.start()
1.400 + import_logger.info("Initial import started.")
1.401 +
1.402 + def startUpdateTemplate(self):
1.403 + if self.updateHandler and self.updateHandler.isAlive():
1.404 + import_logger.info("Initial import already running.")
1.405 + return
1.406 + self.updateHandler = UpdateHandler(self)
1.407 + self.updateHandler.start()
1.408 + import_logger.info("Initial import started.")
1.409 +
1.410 +class UpdateHandler(threading.Thread):
1.411 + vmm = None
1.412 + def __init__(self, vmmanager):
1.413 + threading.Thread.__init__(self)
1.414 + self.vmm = vmmanager
1.415 +
1.416 + def run(self):
1.417 + try:
1.418 + self.vmm.updateTemplate()
1.419 + except:
1.420 + import_logger.info("Update template failed. Refer to service log for details.")
1.421 + self.vmm.start(force=True)
1.422 +
1.423 +class InitialImportHandler(threading.Thread):
1.424 + vmm = None
1.425 + def __init__(self, vmmanager):
1.426 + threading.Thread.__init__(self)
1.427 + self.vmm = vmmanager
1.428 +
1.429 + def run(self):
1.430 + try:
1.431 + self.vmm.importTemplate(self.vmm.getMachineFolder() + '\\OsecVM.ova')
1.432 + self.vmm.updateTemplate()
1.433 + except:
1.434 + import_logger.info("Initial import failed. Refer to service log for details.")
1.435 + self.vmm.start(force=True)
1.436 +
1.437 #handles browsing session creation
1.438 class BrowsingHandler(threading.Thread):
1.439 vmm = None
1.440 @@ -879,7 +1024,7 @@
1.441
1.442 try:
1.443 self.vm_name = self.vmm.newSDVM()
1.444 - self.vmm.attachStorage(self.vm_name)
1.445 + self.vmm.attachVDisk(self.vm_name, 'SATA', '0', '0', self.vmm.templateImage)
1.446 self.vmm.genCertificate(self.vm_name)
1.447 self.vmm.attachCertificate(self.vm_name)
1.448
1.449 @@ -990,7 +1135,7 @@
1.450 showTrayMessage('Mounting device...', 7000)
1.451 if (self.attachedRSDs and False) or (new_device not in self.attachedRSDs.values()):
1.452 new_sdvm = self.vmm.newSDVM()
1.453 - self.vmm.attachStorage(new_sdvm)
1.454 + self.vmm.attachVDisk(new_sdvm, 'SATA', '0', '0', self.vmm.templateImage)
1.455 self.vmm.startVM(new_sdvm)
1.456 new_ip = self.vmm.waitStartup(new_sdvm)
1.457 if new_ip == None: