added scanner scripts
authormb
Sat, 04 May 2013 12:17:31 -0400
changeset 1446a7ba98309
parent 0 70c307de9b84
child 2 c9bf2537109a
child 3 65432e6c6042
added scanner scripts
ait/poc/scanner/99-qubes_block.rule
ait/poc/scanner/create_dvm.py
ait/poc/scanner/scan.py
ait/poc/scanner/start_scan.sh
ait/poc/scanner/test.py
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/ait/poc/scanner/99-qubes_block.rule	Sat May 04 12:17:31 2013 -0400
     1.3 @@ -0,0 +1,20 @@
     1.4 +# Expose all (except xen-frontend) block devices via xenstore
     1.5 +
     1.6 +# Only block devices are interesting
     1.7 +SUBSYSTEM!="block", GOTO="qubes_block_end"
     1.8 +
     1.9 +# Skip xen-blkfront devices
    1.10 +ENV{MAJOR}=="202", GOTO="qubes_block_end"
    1.11 +
    1.12 +# Skip device-mapper devices
    1.13 +ENV{MAJOR}=="253", GOTO="qubes_block_end"
    1.14 +
    1.15 +IMPORT{db}="QUBES_EXPOSED"
    1.16 +ACTION=="add", IMPORT{program}="/usr/lib/qubes/block_add_change"
    1.17 +ACTION=="change", IMPORT{program}="/usr/lib/qubes/block_add_change"
    1.18 +ACTION=="remove", RUN+="/usr/lib/qubes/block_remove"
    1.19 +
    1.20 +LABEL="qubes_block_end"
    1.21 +
    1.22 +# Cleanup disconnected frontend from xenstore
    1.23 +ACTION=="remove", SUBSYSTEM=="block", ENV{MAJOR}=="202", RUN+="/usr/lib/qubes/block_cleanup"
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/ait/poc/scanner/create_dvm.py	Sat May 04 12:17:31 2013 -0400
     2.3 @@ -0,0 +1,280 @@
     2.4 +#!/bin/python
     2.5 +import os
     2.6 +import time
     2.7 +import dbus
     2.8 +import sys
     2.9 +import subprocess
    2.10 +from qubes.qubes import QubesVmCollection
    2.11 +from qubes.qubes import QubesDispVmLabels
    2.12 +from qubes.qubes import QubesException
    2.13 +from qubes.qubes import QubesVmLabels
    2.14 +from qubes.qmemman_client import QMemmanClient
    2.15 +from qubes.qubesutils import block_list,block_attach,block_detach,block_detach_all,block_check_attached
    2.16 +from qubes.qubesutils import kbytes_to_kmg, bytes_to_kmg
    2.17 +
    2.18 +
    2.19 +notify_object = None
    2.20 +current_savefile = '/var/run/qubes/current_savefile'
    2.21 +current_dvm_conf = '/var/run/qubes/current_dvm.conf'
    2.22 +avir_appvm_template = 'avir-template'
    2.23 +avir_dvm_template = 'avir-template-dvm'
    2.24 +
    2.25 +def get_vm_collection():
    2.26 +	vm_collection = QubesVmCollection()
    2.27 +	vm_collection.lock_db_for_reading()
    2.28 +	vm_collection.load()
    2.29 +	vm_collection.unlock_db()
    2.30 +	return vm_collection
    2.31 +
    2.32 +def get_vm_by_name(vmname):
    2.33 +	return get_vm_collection().get_vm_by_name(vmname)
    2.34 +
    2.35 +def gen_scanner_name():
    2.36 +	vm_collection = get_vm_collection()
    2.37 +	vms = [vm for vm in vm_collection.values()]
    2.38 +	vm_names = []
    2.39 +	for vm in vms:
    2.40 +		if vm.is_appvm() and vm.template.name == avir_appvm_template:
    2.41 +			vm_names.append (vm.name)
    2.42 +	print vm_names
    2.43 +
    2.44 +	ids = range(100)
    2.45 +	for id in ids:
    2.46 +		if "scanner"+str(id) not in vm_names:
    2.47 +			return "scanner"+str(id)
    2.48 +	print >> sys.stderr, "Unable to generate new scanner vm name"
    2.49 +	exit(1)
    2.50 +
    2.51 +class VMFactory:
    2.52 +	def __init__(self):
    2.53 +		self.tray_notify(str="Initialized")
    2.54 +
    2.55 +	def tray_notify(self, str, timeout = 3000):
    2.56 +		notify_object.Notify("Qubes", 0, "red", "Qubes", str, [], [], timeout, dbus_interface="org.freedesktop.Notifications")
    2.57 +
    2.58 +	def tray_notify_error(self, str, timeout = 3000):
    2.59 +		notify_object.Notify("Qubes", 0, "dialog-error", "Qubes", str, [], [], timeout, dbus_interface="org.freedesktop.Notifications")
    2.60 +
    2.61 +	def create_appvm(self):
    2.62 +		#generate new avir-scanner name
    2.63 +		scanner_vmname = gen_scanner_name()
    2.64 +		print "Generating new scanner vm %s " % scanner_vmname
    2.65 +
    2.66 +		#create new vscanner virtual machine from template "avir-template"
    2.67 +		qvm_collection = QubesVmCollection()
    2.68 +		qvm_collection.lock_db_for_writing()
    2.69 +		qvm_collection.load()
    2.70 +		avir_template = qvm_collection.get_vm_by_name(avir_appvm_template)
    2.71 +		if not avir_template.is_template():
    2.72 +			print >> sys.stderr, "VM '{0}' is not a TemplateVM".format(avir_template)
    2.73 +			exit (1)
    2.74 +		vmtype = "QubesAppVm"
    2.75 +
    2.76 +		try:
    2.77 +			scanner_vm = qvm_collection.add_new_vm(vmtype, name=scanner_vmname, template=avir_template, label = QubesVmLabels["orange"])
    2.78 +		except QubesException as err:
    2.79 +			print >> sys.stderr, "ERROR: {0}".format(err)
    2.80 +			exit (1)
    2.81 +
    2.82 +		scanner_vm.memory = 512
    2.83 +		scanner_vm.vcpus = 2
    2.84 +		try:
    2.85 +			scanner_vm.create_on_disk(verbose=True, source_template=avir_template)
    2.86 +			#if options.root:
    2.87 +			#       os.unlink(vm.root_img)
    2.88 +			#       os.rename(options.root, vm.root_img)
    2.89 +		except (IOError, OSError) as err:
    2.90 +			print >> sys.stderr, "ERROR: {0}".format(err)
    2.91 +			exit (1)
    2.92 +
    2.93 +		qvm_collection.save()
    2.94 +		qvm_collection.unlock_db()
    2.95 +		return scanner_vmname
    2.96 +
    2.97 +	def start_vm(self, vmname):
    2.98 +		vm = get_vm_by_name(vmname)
    2.99 +		if vm is None or vm.qid not in get_vm_collection():
   2.100 +			print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
   2.101 +			exit(1)
   2.102 +		try:
   2.103 +			vm.verify_files()
   2.104 +			xid = vm.start(verbose=True, preparing_dvm=False, start_guid=True, notify_function=None)
   2.105 +		except (IOError, OSError, QubesException, MemoryError) as err:
   2.106 +			#if options.tray:
   2.107 +			#	tray_notify_error(str(err))
   2.108 +			#else:
   2.109 +			print >> sys.stderr, "ERROR: {0}".format(err)
   2.110 +			exit (1)
   2.111 +
   2.112 +	def create_dvm(self):
   2.113 +		qmemman_client = QMemmanClient()
   2.114 +		if not qmemman_client.request_memory(400*1024*1024):
   2.115 +			qmemman_client.close()
   2.116 +			errmsg = 'Not enough memory to create DVM. '
   2.117 +			errmsg +='Terminate some appVM and retry.'
   2.118 +			if os.path.exists('/usr/bin/kdialog'):
   2.119 +				subprocess.call(['/usr/bin/kdialog', '--sorry', errmsg])
   2.120 +			else:
   2.121 +				subprocess.call(['/usr/bin/zenity', '--warning', errmsg])
   2.122 +			return None
   2.123 +		self.tray_notify("Starting new DispVM...")
   2.124 +
   2.125 +		qvm_collection = QubesVmCollection()
   2.126 +		qvm_collection.lock_db_for_writing()
   2.127 +		qvm_collection.load()
   2.128 +		avir_template = qvm_collection.get_vm_by_name(avir_dvm_template)
   2.129 +		if avir_template is None:
   2.130 +			sys.stderr.write( 'Domain ' + avir_dvm_template + ' does not exist ?')
   2.131 +			qvm_collection.unlock_db()
   2.132 +			qmemman_client.close()
   2.133 +			return None
   2.134 +		label = avir_template.label
   2.135 +		retcode = subprocess.call(['/usr/lib/qubes/qubes_restore',
   2.136 +			current_savefile,
   2.137 +			current_dvm_conf,
   2.138 +			'-u', str(avir_template.default_user),
   2.139 +			'-c', label.color,
   2.140 +			'-i', label.icon_path,
   2.141 +			'-l', str(label.index)])
   2.142 +		qmemman_client.close()
   2.143 +		if retcode != 0:
   2.144 +			if os.path.exists('/usr/bin/kdialog'):
   2.145 +				subprocess.call(['/usr/bin/kdialog', '--sorry', 'DisposableVM creation failed, see qubes_restore.log'])
   2.146 +			else:
   2.147 +				subprocess.call(['/usr/bin/zenity', '--warning', 'DisposableVM creation failed, see qubes_restore.log'])
   2.148 +			qvm_collection.unlock_db()
   2.149 +			return None
   2.150 +
   2.151 +		f = open('/var/run/qubes/dispVM_xid', 'r');
   2.152 +		disp_xid = f.readline().rstrip('\n')
   2.153 +		disp_name = f.readline().rstrip('\n')
   2.154 +		disptempl = f.readline().rstrip('\n')
   2.155 +		f.close()
   2.156 +		
   2.157 +		print >>sys.stderr, "getting vm %s" % disptempl	
   2.158 +		avir_disptempl = qvm_collection.get_vm_by_name(disptempl);
   2.159 +		if avir_disptempl is None:
   2.160 +			sys.stderr.write( 'Domain ' + disptempl + ' does not exist ?')
   2.161 +			qvm_collection.unlock_db()
   2.162 +			return None
   2.163 +
   2.164 +		dispid = int(disp_name[4:])
   2.165 +		dispvm = qvm_collection.add_new_disposablevm(disp_name, avir_disptempl.template, label=label, dispid=dispid, netvm=avir_disptempl.netvm)
   2.166 +		print >> sys.stderr, "Waiting for the VM %s to startup...", dispvm.name
   2.167 +		startup_counter = 0
   2.168 +		startup_counter_max = 60
   2.169 +		while startup_counter < startup_counter_max:
   2.170 +			if dispvm.is_running():
   2.171 +				break
   2.172 +			shutdown_counter += 1
   2.173 +			time.sleep (1)
   2.174 +
   2.175 +		qvm_collection.save()
   2.176 +		qvm_collection.unlock_db()
   2.177 +		return dispvm.name
   2.178 +
   2.179 +	def stop_vm(self, vmname):
   2.180 +		vm = get_vm_by_name(vmname)
   2.181 +		if vm is None or vm.qid not in get_vm_collection():
   2.182 +			print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
   2.183 +			exit(1)
   2.184 +		vm.shutdown(force=True)
   2.185 +		print >> sys.stderr, "Waiting for the VM %s to shutdown...", vmname
   2.186 +		shutdown_counter = 0
   2.187 +		shutdown_counter_max = 60
   2.188 +		while shutdown_counter < shutdown_counter_max:
   2.189 +			if not vm.is_running():
   2.190 +				return
   2.191 +			shutdown_counter += 1
   2.192 +			time.sleep (1)
   2.193 +
   2.194 +	def remove_vm(self, vmname):
   2.195 +		qvm_collection = QubesVmCollection()
   2.196 +		qvm_collection.lock_db_for_writing()
   2.197 +		qvm_collection.load()
   2.198 +		vm = qvm_collection.get_vm_by_name(vmname)
   2.199 +
   2.200 +		if vm is None or vm.qid not in qvm_collection:
   2.201 +			print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
   2.202 +			exit(1)
   2.203 +
   2.204 +		if vm.is_running():
   2.205 +			print >> sys.stderr, "Cannot remove a running VM, stop it first"
   2.206 +			exit (1)
   2.207 +
   2.208 +		if vm.is_template():
   2.209 +			dependent_vms = qvm_collection.get_vms_based_on(vm.qid)
   2.210 +			if len(dependent_vms) > 0:
   2.211 +				print >> sys.stderr, "The following AppVMs use '{0}' as a template:".format(vmname)
   2.212 +				for vm in dependent_vms:
   2.213 +					print >> sys.stderr, "{name:<12} (qid={qid})".format(qid=vm.qid, name=vm.name)
   2.214 +				print >> sys.stderr, "Please remove those VMs first."
   2.215 +				exit (1)
   2.216 +			if qvm_collection.default_template_qid == vm.qid:
   2.217 +				qvm_collection.default_template_qid = None
   2.218 +
   2.219 +		try:
   2.220 +			vm.remove_from_disk()
   2.221 +		except (IOError, OSError) as err:
   2.222 +			print >> sys.stderr, "Warning: {0}".format(err)
   2.223 +
   2.224 +		# Do not exit, perhaps the VM files were somehow removed
   2.225 +		# so just remove it from Qubes DB
   2.226 +		qvm_collection.pop(vm.qid)
   2.227 +		qvm_collection.save()
   2.228 +		qvm_collection.unlock_db()
   2.229 +
   2.230 +	def attach_dev(self, vmname, devname):
   2.231 +		vm = get_vm_by_name(vmname)
   2.232 +		if vm is None or vm.qid not in get_vm_collection():
   2.233 +			print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
   2.234 +			exit(1)
   2.235 +		print "Attaching %s to vm - %s" % (devname, vm.name)
   2.236 +		kwargs = {}
   2.237 +		kwargs['auto_detach'] = True
   2.238 +		try:
   2.239 +			backend_vm = get_vm_by_name("dom0")
   2.240 +			block_attach(vm, backend_vm, devname, **kwargs)
   2.241 +		except QubesException as e:
   2.242 +			print >> sys.stderr, "ERROR: %s" % str(e)
   2.243 +			exit(1)
   2.244 +
   2.245 +	def detach_dev(self, vmname, devname):
   2.246 +		vm = get_vm_by_name(vmname)
   2.247 +		if vm is None or vm.qid not in get_vm_collection():
   2.248 +			print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
   2.249 +			exit(1)
   2.250 +		print "Detaching %s from vm - %s" % (devname, vmname)
   2.251 +		kwargs = {}
   2.252 +		#kwargs['frontend'] = "to_scan"
   2.253 +		try:
   2.254 +			block_detach(vm, **kwargs)
   2.255 +		except QubesException as e:
   2.256 +			print >> sys.stderr, "ERROR: %s" % str(e)
   2.257 +			sys.exit(1)
   2.258 +
   2.259 +	def scan(self, vmname):
   2.260 +		vm = get_vm_by_name(vmname)
   2.261 +		if vm is None or vm.qid not in get_vm_collection():
   2.262 +			print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
   2.263 +			exit(1)
   2.264 +		subprocess.call(['/usr/lib/qubes/qrexec_client', '-d', vmname, 'root:mount /dev/xvdi /mnt/removable'])
   2.265 +		#subprocess.call(['/usr/lib/qubes/qrexec_client', '-d', vmname, 'root:clamscan /mnt/removable'])
   2.266 +		subprocess.call(['/usr/lib/qubes/qrexec_client', '-d', vmname, 'root:umount /mnt/removable'])
   2.267 +
   2.268 +
   2.269 +def main():
   2.270 +	global notify_object
   2.271 +	print >>sys.stderr, "time=%s, qfile-daemon-dvm init" % (str(time.time()))
   2.272 +	notify_object = dbus.SessionBus().get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
   2.273 +	vm_factory = VMFactory()
   2.274 +	#vmname = vm_factory.create_dvm()
   2.275 +	vmname = vm_factory.create_appvm()
   2.276 +	vm_factory.start_vm(vmname)
   2.277 +	vm_factory.attach_dev(vmname, "sdb")
   2.278 +	vm_factory.scan(vmname)
   2.279 +	vm_factory.detach_dev(vmname, "sdb")
   2.280 +	#vm_factory.stop_vm(vmname)
   2.281 +	#vm_factory.remove_vm(vmname) 
   2.282 +
   2.283 +main()
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/ait/poc/scanner/start_scan.sh	Sat May 04 12:17:31 2013 -0400
     3.3 @@ -0,0 +1,3 @@
     3.4 +#!/bin/bash
     3.5 +python /home/bartham/scan.py $1 &
     3.6 +exit 0
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/ait/poc/scanner/test.py	Sat May 04 12:17:31 2013 -0400
     4.3 @@ -0,0 +1,7 @@
     4.4 +#!/bin/python
     4.5 +import subprocess
     4.6 +
     4.7 +def main():
     4.8 +	subprocess.call(['/usr/lib/qubes/qrexec_client', '-d', 'scanner1', 'root:ls -la'])
     4.9 +
    4.10 +main()