mb@63: #!/bin/env python mb@63: # -*- coding: utf-8 -*- mb@63: mb@63: # ------------------------------------------------------------ mb@63: # opensecurityd BarthaM@212: # mb@63: # the opensecurityd as RESTful server mb@63: # mb@63: # Autor: Oliver Maurhart, BarthaM@212: # Mihai Bartha, mb@63: # oliver@240: # Copyright 2013-2014 X-Net and AIT Austrian Institute of Technology mb@63: # mb@63: # oliver@240: # X-Net Services GmbH oliver@240: # Elisabethstrasse 1 oliver@240: # 4020 Linz oliver@240: # AUSTRIA oliver@240: # https://www.x-net.at oliver@240: # oliver@240: # AIT Austrian Institute of Technology oliver@240: # Donau City Strasse 1 oliver@240: # 1220 Wien oliver@240: # AUSTRIA oliver@240: # http://www.ait.ac.at oliver@240: # oliver@240: # oliver@240: # Licensed under the Apache License, Version 2.0 (the "License"); oliver@240: # you may not use this file except in compliance with the License. oliver@240: # You may obtain a copy of the License at oliver@240: # oliver@240: # http://www.apache.org/licenses/LICENSE-2.0 oliver@240: # oliver@240: # Unless required by applicable law or agreed to in writing, software oliver@240: # distributed under the License is distributed on an "AS IS" BASIS, oliver@240: # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. oliver@240: # See the License for the specific language governing permissions and oliver@240: # limitations under the License. mb@63: # ------------------------------------------------------------ mb@63: mb@63: mb@63: # ------------------------------------------------------------ mb@63: # imports mb@63: oliver@130: import json BarthaM@223: #import os mb@63: import os.path BarthaM@223: #import subprocess mb@63: import sys oliver@91: import tempfile mb@63: import web mb@63: oliver@87: import vmmanager mb@63: mb@63: # local oliver@144: import __init__ as opensecurity oliver@91: from cygwin import Cygwin oliver@147: from environment import Environment oliver@193: from opensecurity_util import logger, showTrayMessage oliver@193: mb@63: mb@63: mb@63: # ------------------------------------------------------------ mb@63: # const mb@63: mb@63: """All the URLs we know mapping to class handler""" mb@63: opensecurity_urls = ( mb@63: '/browsing', 'os_browsing', # http://localhost:8080/browsing GET oliver@91: '/fetch_initial_image', 'os_fetch_image', # http://localhost:8080/fetch_initial_image GET oliver@91: '/init', 'os_init', # http://localhost:8080/init GET oliver@107: '/initial_image', 'os_initial_image', # http://localhost:8080/initial_image GET mb@63: '/sdvms', 'os_sdvms', # http://localhost:8080/sdvms GET, PUT mb@63: '/sdvms/(.*)/application/(.*)', 'os_sdvm_application', # http://localhost:8080/sdvms/[VMNAME]/application/[COMMAND] GET mb@63: '/sdvms/(.*)/ip', 'os_sdvm_ip', # http://localhost:8080/sdvms/[VMNAME]/ip GET mb@63: '/sdvms/(.*)/start', 'os_sdvm_start', # http://localhost:8080/sdvms/[VMNAME]/start GET mb@63: '/sdvms/(.*)/stop', 'os_sdvm_stop', # http://localhost:8080/sdvms/[VMNAME]/stop GET mb@63: '/sdvms/(.*)', 'os_sdvm', # http://localhost:8080/sdvms/[VMNAME] GET, DELETE oliver@93: '/setup', 'os_setup', # http://localhost:8080/setup GET mb@63: '/vms', 'os_vms', # http://localhost:8080/vms GET mb@63: '/vms/(.*)', 'os_vm', # http://localhost:8080/vms/[VMNAME] GET oliver@87: '/update_template', 'os_update_template', # http://localhost:8080/update_template GET oliver@87: '/terminate', 'os_terminate', # http://localhost:8080/terminate GET BarthaM@212: '/initialize', 'os_initialize', # http://localhost:8080/initialize GET oliver@87: '/', 'os_root' # http://localhost:8080/ GET mb@63: ) mb@63: oliver@87: mb@66: # ------------------------------------------------------------ mb@63: # vars mb@63: mb@63: # Global VMManager instance oliver@86: gvm_mgr = None oliver@86: oliver@138: # server instance oliver@138: server = None oliver@138: oliver@138: mb@63: # ------------------------------------------------------------ mb@63: # code mb@63: mb@63: mb@63: class os_browsing: mb@63: """OpenSecurity '/browsing' handler mb@63: mb@63: - GET: Start and prepare a new SecurityVM for Internet Browsing. Return the name of the VM. mb@63: """ mb@63: mb@63: def GET(self): BarthaM@213: args = web.input() oliver@74: log_call(web.ctx.environ) oliver@87: global gvm_mgr mb@63: try: BarthaM@213: proxy = None BarthaM@223: wpad = None BarthaM@213: if 'ProxyServer' in args: BarthaM@213: proxy = args['ProxyServer'] BarthaM@223: if 'ProxyAutoConfigURL' in args: BarthaM@223: wpad = args['ProxyAutoConfigURL'] BarthaM@223: result = gvm_mgr.handleBrowsingRequest(proxy, wpad) mb@90: return result mb@63: except: mb@63: raise web.internalerror() mb@63: oliver@87: oliver@91: class os_fetch_image: oliver@91: """OpenSecurity '/fetch_initial_image' handler oliver@91: oliver@91: - GET: fetch the initial image from the X-Net Servers oliver@91: The initial image is stored in the oliver@91: Virtual Box default machine path. oliver@91: The result to this call is a temprary file oliver@91: which shows the progress (or error state) oliver@91: of this call. oliver@91: """ oliver@91: oliver@91: def GET(self): oliver@91: oliver@91: log_call(web.ctx.environ) oliver@91: global gvm_mgr oliver@91: oliver@147: trace_file_name = os.path.join(Environment('OpenSecurity').log_path, 'OpenSecurity_fetch_image.log') oliver@91: trace_file = open(trace_file_name, 'w+') oliver@91: oliver@91: machine_folder = Cygwin.cygPath(gvm_mgr.getMachineFolder()) oliver@164: download_initial_image_script = Cygwin.cygPath(os.path.abspath(os.path.join(os.path.split(__file__)[0], 'download_initial_image.sh'))) BarthaM@170: Cygwin.bashExecute('\\"' + download_initial_image_script + '\\" \'' + machine_folder + '\'', wait_return = False, stdout = trace_file, stderr = trace_file) oliver@91: oliver@116: res = '{ "fetch_log": "' + trace_file_name.replace('\\', '\\\\') + '" }' oliver@115: return res oliver@91: oliver@147: oliver@91: class os_init: oliver@91: """OpenSecurity '/init' handler oliver@91: oliver@91: - GET: Do initial import of OsecVM.ova oliver@91: """ oliver@91: oliver@91: def GET(self): BarthaM@221: global gvm_mgr oliver@91: log_call(web.ctx.environ) oliver@91: BarthaM@221: gvm_mgr.startInitialImport() BarthaM@221: res = '{ "init_log": "' + (Environment('OpenSecurity').log_path+'\\OpenSecurity_initial_import.log').replace('\\', '\\\\') + '" }' oliver@115: return res oliver@91: BarthaM@221: class os_update_template: BarthaM@221: """OpenSecurity '/update_template' handler BarthaM@221: BarthaM@221: - GET: update template vm BarthaM@221: """ BarthaM@221: BarthaM@221: def GET(self): BarthaM@221: global gvm_mgr BarthaM@221: log_call(web.ctx.environ) oliver@91: BarthaM@221: gvm_mgr.startUpdateTemplate() BarthaM@221: res = '{ "init_log": "' + (Environment('OpenSecurity').log_path+'\\OpenSecurity_initial_import.log').replace('\\', '\\\\') + '" }' BarthaM@221: return res BarthaM@221: oliver@107: class os_initial_image: oliver@107: """OpenSecurity '/initial_image' handler oliver@107: oliver@107: - GET: Return what we have as initial image. oliver@107: """ oliver@107: oliver@107: def GET(self): oliver@107: log_call(web.ctx.environ) oliver@107: global gvm_mgr oliver@107: t = os.path.join(gvm_mgr.systemProperties['Default machine folder'], 'OsecVM.ova') oliver@107: res = '' oliver@107: if os.path.isfile(t): oliver@107: res = '{"initial_template": { ' oliver@107: res += '"name": "OsecVM.ova", ' oliver@107: res += '"path": "' + t.replace('\\', '\\\\') + '", ' oliver@107: res += '"size": ' + str(os.path.getsize(t)) + ', ' oliver@107: res += '"date": ' + str(os.path.getmtime(t)) + '' oliver@112: res += '}}' oliver@107: return res BarthaM@221: oliver@87: class os_root: oliver@87: """OpenSecurity '/' handler oliver@87: oliver@87: - GET: give information about current installation. oliver@87: """ oliver@87: oliver@87: def GET(self): oliver@87: log_call(web.ctx.environ) oliver@87: global gvm_mgr oliver@130: oliver@130: # create a json string and pretty print it oliver@107: res = '{"os_server": { ' oliver@144: res += '"version": "' + opensecurity.__version__ + '" ' oliver@130: res += ', "virtual box systemproperties": ' + str(gvm_mgr.systemProperties).replace("'", '"') oliver@130: res += ', "current temporary folder": "' + tempfile.gettempdir().replace('\\', '\\\\') + '"' oliver@147: res += ', "current log folder": "' + Environment('OpenSecurity').log_path.replace('\\', '\\\\') + '"' oliver@130: oliver@130: try: oliver@130: res += ', "whoami": "' + Cygwin.bashExecute('whoami')[1].strip() + '"' oliver@130: except: oliver@130: res += ', "whoami": "FAILED"' oliver@130: oliver@130: try: oliver@130: res += ', "mount": ' + str(Cygwin.bashExecute('mount')[1].split('\n')[:-1]).replace("'", '"') oliver@130: except: oliver@130: res += ', "mount": "FAILED"' oliver@130: oliver@130: try: oliver@130: res += ', "cygpath --windows ~": "' + Cygwin.bashExecute('cygpath --windows ~')[1].strip().replace('\\', '\\\\') + '"' oliver@130: except: oliver@130: res += ', "cygpath --windows ~": "FAILED"' oliver@130: oliver@131: oliver@131: res += ', "status message": "' + gvm_mgr.status_message.replace('"', "'") + '"' oliver@131: oliver@107: res += '}}' oliver@130: oliver@130: # loading it into json and print it again ensures oliver@130: # we really do have a valid RFC conform json string oliver@130: # created (as long as the python json module is RFC conform) oliver@130: return json.dumps(json.loads(res), indent = 4) oliver@87: oliver@87: oliver@204: mb@63: class os_sdvm: mb@63: """OpenSecurity '/sdvms/[VM]' handler mb@63: mb@63: - GET: Information about a specific SecurityVM mb@63: - DELETE: Remove a specific mb@63: """ mb@63: mb@63: def GET(self, name): oliver@74: log_call(web.ctx.environ) oliver@87: global gvm_mgr oliver@203: return json.dumps(gvm_mgr.getVMInfo(name), indent = 4) mb@63: mb@63: def DELETE(self, name): oliver@74: log_call(web.ctx.environ) oliver@87: global gvm_mgr oliver@87: return gvm_mgr.removeVM(name) mb@63: mb@63: mb@63: class os_sdvm_application: mb@63: """OpenSecurity '/sdvms/[VM]/application/[CMD]' handler mb@63: mb@63: - GET: start application with given command in the VM. mb@63: """ mb@63: mb@63: def GET(self, name, command): oliver@74: log_call(web.ctx.environ) oliver@87: global gvm_mgr mb@63: command = '/' + command oliver@193: showTrayMessage('Launching application in isolated VM...', 7000) BarthaM@223: Cygwin.sshExecuteX11(command, gvm_mgr.getHostOnlyIP(name), 'osecuser', Cygwin.cygPath(gvm_mgr.getMachineFolder()) + '/' + name + '/dvm_key' ) oliver@165: return 'Command ' + str(command) + ' started on VM "' + name + '" with IP ' + gvm_mgr.getHostOnlyIP(name) mb@63: mb@63: mb@63: class os_sdvm_ip: mb@63: """OpenSecurity '/sdvms/[VM]/ip' handler mb@63: mb@63: - GET: give IP of SecurityVM. mb@63: """ mb@63: mb@63: def GET(self, name): oliver@74: log_call(web.ctx.environ) oliver@87: global gvm_mgr oliver@87: return gvm_mgr.getHostOnlyIP(name) mb@63: mb@63: mb@63: class os_sdvm_start: mb@63: """OpenSecurity '/sdvms/[VM]/start' handler mb@63: mb@63: - GET: Start specific SecuirtyVM. mb@63: """ mb@63: mb@63: def GET(self, name): oliver@74: log_call(web.ctx.environ) oliver@87: global gvm_mgr oliver@87: return gvm_mgr.startVM(name) mb@63: mb@63: mb@63: class os_sdvm_stop: mb@63: """OpenSecurity '/sdvms/[VM]/stop' handler mb@63: mb@63: - GET: stop specific Secuirty VM. mb@63: """ mb@63: mb@63: def GET(self, name): oliver@74: log_call(web.ctx.environ) oliver@87: global gvm_mgr oliver@87: return gvm_mgr.stopVM(name) mb@63: mb@63: mb@63: class os_sdvms: mb@63: """OpenSecurity '/sdvms' handler mb@63: mb@63: - GET: list all available secuirty VMs. mb@63: - POST: create new security vm. mb@63: """ mb@63: mb@63: def GET(self): mb@63: """get the list of SDVMs""" oliver@74: log_call(web.ctx.environ) oliver@87: global gvm_mgr oliver@204: oliver@204: d = {} oliver@204: for sdvm in gvm_mgr.listSDVM(): oliver@204: d[sdvm] = gvm_mgr.getHostOnlyIP(sdvm) oliver@204: oliver@204: return json.dumps(d, indent = 4) mb@63: mb@63: def POST(self): mb@63: """create a new SDVM""" oliver@74: log_call(web.ctx.environ) oliver@87: global gvm_mgr oliver@74: mb@63: # get a new vm-name oliver@87: name = gvm_mgr.generateSDVMName() mb@63: try: oliver@87: gvm_mgr.createVM(name) mb@63: except: mb@63: raise web.internalerror() mb@63: mb@63: return name mb@63: oliver@87: oliver@93: class os_setup: oliver@93: """OpenSecurity '/setup' handler oliver@93: BarthaM@172: - GET: Give user some info how to setup the OpenSecurity environment oliver@93: """ oliver@93: oliver@93: def GET(self): oliver@93: oliver@93: log_call(web.ctx.environ) oliver@93: oliver@93: page = """ oliver@93: oliver@93: oliver@93:

Setup OpenSecurity

oliver@93: In order to setup OpenSecurity an inital VM image has to be downloaded and imported:
oliver@93: oliver@93: oliver@93: oliver@93: """ oliver@93: return page oliver@93: oliver@93: oliver@87: class os_terminate: oliver@87: """OpenSecurity '/terminate' handler oliver@87: oliver@87: - GET: terminate the opensecurityd. oliver@87: oliver@87: TODO: need to find a better way doing this, and not via the oliver@87: REST api. Maybe hack web.py server code? oliver@87: """ oliver@87: oliver@87: def GET(self): oliver@87: log_call(web.ctx.environ) oliver@139: global gvm_mgr BarthaM@170: gvm_mgr.stop() oliver@139: gvm_mgr.cleanup() oliver@138: global server oliver@138: server.stop() oliver@87: return None oliver@87: BarthaM@212: class os_initialize: BarthaM@212: """OpenSecurity '/initialize' handler BarthaM@212: BarthaM@212: - GET: initialize / starts the vmmanager. BarthaM@212: BarthaM@212: """ BarthaM@212: BarthaM@212: def GET(self): BarthaM@212: log_call(web.ctx.environ) BarthaM@212: global gvm_mgr BarthaM@212: gvm_mgr.cleanup() BarthaM@212: gvm_mgr.start() BarthaM@221: #global server BarthaM@221: #server.run() BarthaM@212: return None oliver@87: mb@63: class os_vm: mb@63: """OpenSecurity '/vms/[VM]' handler mb@63: mb@63: - GET: list information of arbitrary VM. mb@63: """ mb@63: mb@63: def GET(self, name): oliver@74: log_call(web.ctx.environ) oliver@87: global gvm_mgr oliver@87: return gvm_mgr.getVMInfo(name) mb@63: mb@63: mb@63: class os_vms: mb@63: """OpenSecurity '/vms' handler mb@63: mb@63: - GET: list all (also non Security) VMs. mb@63: """ mb@63: mb@63: def GET(self): oliver@74: log_call(web.ctx.environ) oliver@87: global gvm_mgr mihai@248: return str(gvm_mgr.listVMS()).replace("'",'"') mb@63: mb@63: oliver@74: def log_call(web_environ): oliver@74: """log the incoming call to the REST api""" oliver@74: try: oliver@74: call = 'REST ' + web_environ['REQUEST_METHOD'] + ' ' + web_environ['REQUEST_URI'] + ' from ' + web_environ['REMOTE_ADDR'] + ':' + web_environ['REMOTE_PORT'] oliver@74: logger.debug(call) oliver@74: except: oliver@74: pass oliver@74: oliver@86: oliver@86: def main(): mihai@252: """main startup for the opensecurityd""" oliver@87: oliver@139: global gvm_mgr oliver@139: global server oliver@139: oliver@87: logger.debug('Starting OpenSecurity REST server') oliver@87: oliver@87: # ensure a VMManger is yet loaded oliver@87: gvm_mgr = vmmanager.VMManager.getInstance() BarthaM@212: gvm_mgr.start() oliver@98: # tweak sys.argv to control wep.py server start behavior oliver@98: sys.argv = [__file__, "8080"] oliver@87: server = web.application(opensecurity_urls, globals(), autoreload = False) mb@63: server.run() oliver@87: oliver@87: logger.debug('Stopped OpenSecurity REST server') oliver@86: oliver@86: oliver@88: def stop(): oliver@88: """stop the opensecuirityd""" oliver@88: oliver@88: # calling sys.exit() raises a SystemExit exception oliver@88: # of the WSGI Server to let it wind down oliver@89: # gracefully oliver@88: sys.exit(0) oliver@88: oliver@86: # start oliver@86: if __name__ == "__main__": oliver@86: main() BarthaM@170: sys.exit(0) oliver@86: