OpenSecurity/bin/opensecurityd.pyw
author Oliver Maurhart <oliver.maurhart@ait.ac.at>
Wed, 25 Jun 2014 20:46:31 +0200
changeset 203 0cc33b647a4e
parent 193 8d5b7c9ff783
child 204 0c3136908f4f
permissions -rwxr-xr-x
machine configuration tab working
     1 #!/bin/env python
     2 # -*- coding: utf-8 -*-
     3 
     4 # ------------------------------------------------------------
     5 # opensecurityd
     6 # 
     7 # the opensecurityd as RESTful server
     8 #
     9 # Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
    10 #
    11 # Copyright (C) 2013 AIT Austrian Institute of Technology
    12 # AIT Austrian Institute of Technology GmbH
    13 # Donau-City-Strasse 1 | 1220 Vienna | Austria
    14 # http://www.ait.ac.at
    15 #
    16 # This program is free software; you can redistribute it and/or
    17 # modify it under the terms of the GNU General Public License
    18 # as published by the Free Software Foundation version 2.
    19 # 
    20 # This program is distributed in the hope that it will be useful,
    21 # but WITHOUT ANY WARRANTY; without even the implied warranty of
    22 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    23 # GNU General Public License for more details.
    24 # 
    25 # You should have received a copy of the GNU General Public License
    26 # along with this program; if not, write to the Free Software
    27 # Foundation, Inc., 51 Franklin Street, Fifth Floor, 
    28 # Boston, MA  02110-1301, USA.
    29 # ------------------------------------------------------------
    30 
    31 
    32 # ------------------------------------------------------------
    33 # imports
    34 
    35 import json
    36 import os
    37 import os.path
    38 import subprocess
    39 import sys
    40 import tempfile
    41 import web
    42 
    43 import vmmanager
    44 
    45 # local
    46 import __init__ as opensecurity
    47 from cygwin import Cygwin
    48 from environment import Environment
    49 from opensecurity_util import logger, showTrayMessage
    50 
    51 
    52 
    53 # ------------------------------------------------------------
    54 # const
    55 
    56 """All the URLs we know mapping to class handler"""
    57 opensecurity_urls = (
    58     '/browsing',                        'os_browsing',          # http://localhost:8080/browsing                                GET
    59     '/fetch_initial_image',             'os_fetch_image',       # http://localhost:8080/fetch_initial_image                     GET
    60     '/init',                            'os_init',              # http://localhost:8080/init                                    GET
    61     '/initial_image',                   'os_initial_image',     # http://localhost:8080/initial_image                           GET
    62     '/sdvms',                           'os_sdvms',             # http://localhost:8080/sdvms                                   GET, PUT
    63     '/sdvms/(.*)/application/(.*)',     'os_sdvm_application',  # http://localhost:8080/sdvms/[VMNAME]/application/[COMMAND]    GET
    64     '/sdvms/(.*)/ip',                   'os_sdvm_ip',           # http://localhost:8080/sdvms/[VMNAME]/ip                       GET
    65     '/sdvms/(.*)/start',                'os_sdvm_start',        # http://localhost:8080/sdvms/[VMNAME]/start                    GET
    66     '/sdvms/(.*)/stop',                 'os_sdvm_stop',         # http://localhost:8080/sdvms/[VMNAME]/stop                     GET
    67     '/sdvms/(.*)',                      'os_sdvm',              # http://localhost:8080/sdvms/[VMNAME]                          GET, DELETE
    68     '/setup',                           'os_setup',             # http://localhost:8080/setup                                   GET
    69     '/vms',                             'os_vms',               # http://localhost:8080/vms                                     GET
    70     '/vms/(.*)',                        'os_vm',                # http://localhost:8080/vms/[VMNAME]                            GET
    71     '/update_template',                 'os_update_template',   # http://localhost:8080/update_template                         GET
    72     '/terminate',                       'os_terminate',         # http://localhost:8080/terminate                               GET
    73     '/',                                'os_root'               # http://localhost:8080/                                        GET
    74 )
    75 
    76 
    77 # ------------------------------------------------------------
    78 # vars
    79 
    80 # Global VMManager instance
    81 gvm_mgr = None
    82 
    83 # server instance
    84 server = None
    85 
    86 
    87 # ------------------------------------------------------------
    88 # code
    89 
    90 
    91 class os_browsing:
    92     """OpenSecurity '/browsing' handler
    93     
    94     - GET: Start and prepare a new SecurityVM for Internet Browsing. Return the name of the VM.
    95     """
    96     
    97     def GET(self):
    98         log_call(web.ctx.environ)
    99         global gvm_mgr
   100         try:
   101             result = gvm_mgr.handleBrowsingRequest()
   102             return result
   103         except:
   104             raise web.internalerror()
   105 
   106        
   107 class os_fetch_image:
   108     """OpenSecurity '/fetch_initial_image' handler
   109     
   110     - GET: fetch the initial image from the X-Net Servers
   111             The initial image is stored in the
   112             Virtual Box default machine path.
   113             The result to this call is a temprary file
   114             which shows the progress (or error state)
   115             of this call.
   116     """
   117     
   118     def GET(self):
   119         
   120         log_call(web.ctx.environ)
   121         global gvm_mgr
   122 
   123         trace_file_name = os.path.join(Environment('OpenSecurity').log_path, 'OpenSecurity_fetch_image.log')
   124         trace_file = open(trace_file_name, 'w+')
   125 
   126         machine_folder = Cygwin.cygPath(gvm_mgr.getMachineFolder()) 
   127         download_initial_image_script = Cygwin.cygPath(os.path.abspath(os.path.join(os.path.split(__file__)[0], 'download_initial_image.sh')))
   128         Cygwin.bashExecute('\\"' + download_initial_image_script + '\\" \'' + machine_folder + '\'', wait_return = False, stdout = trace_file, stderr = trace_file) 
   129 
   130         res = '{ "fetch_log": "' + trace_file_name.replace('\\', '\\\\') + '" }'
   131         return res
   132 
   133 
   134 class os_init:
   135     """OpenSecurity '/init' handler
   136     
   137     - GET: Do initial import of OsecVM.ova
   138     """
   139     
   140     def GET(self):
   141         log_call(web.ctx.environ)
   142         global gvm_mgr
   143 
   144         gvm_mgr.stop()
   145         gvm_mgr.cleanup()
   146         
   147         if gvm_mgr.vmRootName in gvm_mgr.listVM():
   148             gvm_mgr.poweroffVM(gvm_mgr.vmRootName)
   149             tmplateUUID = gvm_mgr.getTemplateUUID()
   150             if tmplateUUID != None:
   151                 logger.debug('found parent uuid ' + tmplateUUID)
   152                 gvm_mgr.storageDetach(gvm_mgr.vmRootName)
   153                 gvm_mgr.removeSnapshots(tmplateUUID)
   154                 gvm_mgr.removeImage(tmplateUUID)
   155             else:
   156                 logger.debug('parent uuid not found')
   157             gvm_mgr.removeVM(gvm_mgr.vmRootName)
   158         
   159         trace_file_name = os.path.join(Environment('OpenSecurity').log_path, 'OpenSecurity_initial_import.log')
   160         trace_file = open(trace_file_name, 'w+')
   161 
   162         vm_image = Cygwin.cygPath(gvm_mgr.getMachineFolder()) + '/OsecVM.ova'
   163         initial_import_script = Cygwin.cygPath(os.path.abspath(os.path.join(os.path.split(__file__)[0], 'initial_vm.sh')))
   164         Cygwin.bashExecute('\\"' + initial_import_script + '\\" \'' + vm_image + '\'', wait_return = False, stdout = trace_file, stderr = trace_file) 
   165 
   166         res = '{ "init_log": "' + trace_file_name.replace('\\', '\\\\') + '" }'
   167         return res
   168 
   169 
   170 class os_initial_image:
   171     """OpenSecurity '/initial_image' handler
   172     
   173     - GET: Return what we have as initial image.
   174     """
   175     
   176     def GET(self):
   177         log_call(web.ctx.environ)
   178         global gvm_mgr
   179         t = os.path.join(gvm_mgr.systemProperties['Default machine folder'], 'OsecVM.ova')
   180         res = ''
   181         if os.path.isfile(t):
   182             res = '{"initial_template": { '
   183             res += '"name": "OsecVM.ova", '
   184             res += '"path": "' + t.replace('\\', '\\\\') + '", '
   185             res += '"size": ' + str(os.path.getsize(t)) + ', ' 
   186             res += '"date": ' + str(os.path.getmtime(t)) + ''
   187             res += '}}'
   188         return res
   189 
   190 
   191 class os_root:
   192     """OpenSecurity '/' handler
   193     
   194     - GET: give information about current installation.
   195     """
   196     
   197     def GET(self):
   198         log_call(web.ctx.environ)
   199         global gvm_mgr
   200 
   201         # create a json string and pretty print it
   202         res = '{"os_server": { '
   203         res += '"version": "' + opensecurity.__version__ + '" '
   204         res += ', "virtual box systemproperties": ' + str(gvm_mgr.systemProperties).replace("'", '"') 
   205         res += ', "current temporary folder": "' + tempfile.gettempdir().replace('\\', '\\\\') + '"'
   206         res += ', "current log folder": "' + Environment('OpenSecurity').log_path.replace('\\', '\\\\') + '"'
   207 
   208         try:
   209             res += ', "whoami": "' + Cygwin.bashExecute('whoami')[1].strip() + '"'
   210         except:
   211             res += ', "whoami": "FAILED"'
   212 
   213         try:
   214             res += ', "mount": ' + str(Cygwin.bashExecute('mount')[1].split('\n')[:-1]).replace("'", '"')
   215         except:
   216             res += ', "mount": "FAILED"'
   217 
   218         try:
   219             res += ', "cygpath --windows ~": "' + Cygwin.bashExecute('cygpath --windows ~')[1].strip().replace('\\', '\\\\') + '"'
   220         except:
   221             res += ', "cygpath --windows ~": "FAILED"'
   222 
   223 
   224         res += ', "status message": "' + gvm_mgr.status_message.replace('"', "'") + '"'
   225 
   226         res += '}}'
   227 
   228         # loading it into json and print it again ensures
   229         # we really do have a valid RFC conform json string
   230         # created (as long as the python json module is RFC conform)
   231         return json.dumps(json.loads(res), indent = 4)
   232 
   233 
   234 class os_sdvm:
   235     """OpenSecurity '/sdvms/[VM]' handler
   236     
   237     - GET: Information about a specific SecurityVM
   238     - DELETE: Remove a specific
   239     """
   240     
   241     def GET(self, name):
   242         log_call(web.ctx.environ)
   243         global gvm_mgr
   244         return json.dumps(gvm_mgr.getVMInfo(name), indent = 4)
   245 
   246     def DELETE(self, name):
   247         log_call(web.ctx.environ)
   248         global gvm_mgr
   249         return gvm_mgr.removeVM(name)
   250             
   251 
   252 class os_sdvm_application:
   253     """OpenSecurity '/sdvms/[VM]/application/[CMD]' handler
   254     
   255     - GET: start application with given command in the VM.
   256     """
   257     
   258     def GET(self, name, command):
   259         log_call(web.ctx.environ)
   260         global gvm_mgr
   261         command = '/' + command
   262         showTrayMessage('Launching application in isolated VM...', 7000)
   263         result = Cygwin.sshExecuteX11(command, gvm_mgr.getHostOnlyIP(name), 'osecuser', Cygwin.cygPath(gvm_mgr.getMachineFolder()) + '/' + name + '/dvm_key'  )
   264         return 'Command ' + str(command) + ' started on VM "' + name + '" with IP ' + gvm_mgr.getHostOnlyIP(name)
   265     
   266 
   267 class os_sdvm_ip:
   268     """OpenSecurity '/sdvms/[VM]/ip' handler
   269     
   270     - GET: give IP of SecurityVM.
   271     """
   272     
   273     def GET(self, name):
   274         log_call(web.ctx.environ)
   275         global gvm_mgr
   276         return gvm_mgr.getHostOnlyIP(name)
   277             
   278 
   279 class os_sdvm_start:
   280     """OpenSecurity '/sdvms/[VM]/start' handler
   281     
   282     - GET: Start specific SecuirtyVM.
   283     """
   284     
   285     def GET(self, name):
   286         log_call(web.ctx.environ)
   287         global gvm_mgr
   288         return gvm_mgr.startVM(name)
   289             
   290 
   291 class os_sdvm_stop:
   292     """OpenSecurity '/sdvms/[VM]/stop' handler
   293     
   294     - GET: stop specific Secuirty VM.
   295     """
   296     
   297     def GET(self, name):
   298         log_call(web.ctx.environ)
   299         global gvm_mgr
   300         return gvm_mgr.stopVM(name)
   301             
   302 
   303 class os_sdvms:
   304     """OpenSecurity '/sdvms' handler
   305     
   306     - GET: list all available secuirty VMs.
   307     - POST: create new security vm.
   308     """
   309     
   310     def GET(self):
   311         """get the list of SDVMs"""
   312         log_call(web.ctx.environ)
   313         global gvm_mgr
   314         return str(gvm_mgr.listSDVM()).replace("'",'"') 
   315             
   316     def POST(self):
   317         """create a new SDVM"""
   318         log_call(web.ctx.environ)
   319         global gvm_mgr
   320         
   321         # get a new vm-name
   322         name = gvm_mgr.generateSDVMName()
   323         try:
   324             gvm_mgr.createVM(name)
   325         except:
   326             raise web.internalerror()
   327             
   328         return name
   329             
   330 
   331 class os_setup:
   332     """OpenSecurity '/setup' handler
   333     
   334     - GET: Give user some info how to setup the OpenSecurity environment
   335     """
   336     
   337     def GET(self):
   338 
   339         log_call(web.ctx.environ)
   340 
   341         page = """
   342         <html>
   343         <body>
   344         <h1>Setup OpenSecurity</h1>
   345         In order to setup OpenSecurity an inital VM image has to be downloaded and imported:<br/>
   346         <ul>
   347             <li>Download initial VM image: <a href="/fetch_initial_image">fetch_initial_image</a>
   348             <li>Import initial VM: <a href="/init">init</a>
   349         </ul>
   350         </body>
   351         </html>
   352         """
   353         return page
   354 
   355 
   356 class os_terminate:
   357     """OpenSecurity '/terminate' handler
   358     
   359     - GET: terminate the opensecurityd.
   360 
   361     TODO: need to find a better way doing this, and not via the
   362           REST api. Maybe hack web.py server code?
   363     """
   364     
   365     def GET(self):
   366         log_call(web.ctx.environ)
   367         global gvm_mgr
   368         gvm_mgr.stop()
   369         gvm_mgr.cleanup()
   370         global server
   371         server.stop()
   372         return None
   373 
   374 
   375 class os_update_template:
   376     """OpenSecurity '/update_template' handler
   377     
   378     - GET: update template vm
   379     """
   380     
   381     def GET(self):
   382         #return gvm_mgr.guestExecute('SecurityDVM', 'sudo apt-get -y update')
   383         global gvm_mgr
   384         log_call(web.ctx.environ)
   385         return gvm_mgr.updateTemplate()
   386 
   387 
   388 class os_vm:
   389     """OpenSecurity '/vms/[VM]' handler
   390     
   391     - GET: list information of arbitrary VM.
   392     """
   393     
   394     def GET(self, name):
   395         log_call(web.ctx.environ)
   396         global gvm_mgr
   397         return gvm_mgr.getVMInfo(name)
   398             
   399 
   400 class os_vms:
   401     """OpenSecurity '/vms' handler
   402     
   403     - GET: list all (also non Security) VMs.
   404     """
   405     
   406     def GET(self):
   407         log_call(web.ctx.environ)
   408         global gvm_mgr
   409         return str(gvm_mgr.listVM()).replace("'",'"')
   410             
   411 
   412 def log_call(web_environ):
   413     """log the incoming call to the REST api"""
   414     try:
   415         call = 'REST ' +  web_environ['REQUEST_METHOD'] + ' ' + web_environ['REQUEST_URI'] + ' from ' + web_environ['REMOTE_ADDR'] + ':' + web_environ['REMOTE_PORT']
   416         logger.debug(call)
   417     except:
   418         pass
   419 
   420 
   421 def main():
   422     """main startup for the opensecuirityd"""
   423 
   424     global gvm_mgr
   425     global server
   426 
   427     logger.debug('Starting OpenSecurity REST server')
   428 
   429     # ensure a VMManger is yet loaded
   430     gvm_mgr = vmmanager.VMManager.getInstance()
   431     
   432     # tweak sys.argv to control wep.py server start behavior
   433     sys.argv = [__file__, "8080"]
   434     server = web.application(opensecurity_urls, globals(), autoreload = False)
   435     server.run()
   436     
   437     logger.debug('Stopped OpenSecurity REST server')
   438 
   439 
   440 def stop():
   441     """stop the opensecuirityd"""
   442 
   443     # calling sys.exit() raises a SystemExit exception
   444     # of the WSGI Server to let it wind down
   445     # gracefully
   446     sys.exit(0)
   447 
   448 # start
   449 if __name__ == "__main__":
   450     main()
   451     sys.exit(0)
   452