OpenSecurity/bin/opensecurityd.pyw
author Oliver Maurhart <oliver.maurhart@ait.ac.at>
Tue, 25 Mar 2014 14:25:34 +0100
changeset 98 4820361279cc
parent 93 8fe521017397
child 107 50cacad1967e
permissions -rwxr-xr-x
fixed install ... finally!
     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 os
    36 import os.path
    37 import subprocess
    38 import sys
    39 import tempfile
    40 import web
    41 
    42 import vmmanager
    43 
    44 # local
    45 from cygwin import Cygwin
    46 from environment import Environment
    47 from opensecurity_util import logger
    48 
    49 
    50 # ------------------------------------------------------------
    51 # const
    52 
    53 __version__ = "0.2.3"
    54 
    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     '/sdvms',                           'os_sdvms',             # http://localhost:8080/sdvms                                   GET, PUT
    62     '/sdvms/(.*)/application/(.*)',     'os_sdvm_application',  # http://localhost:8080/sdvms/[VMNAME]/application/[COMMAND]    GET
    63     '/sdvms/(.*)/ip',                   'os_sdvm_ip',           # http://localhost:8080/sdvms/[VMNAME]/ip                       GET
    64     '/sdvms/(.*)/start',                'os_sdvm_start',        # http://localhost:8080/sdvms/[VMNAME]/start                    GET
    65     '/sdvms/(.*)/stop',                 'os_sdvm_stop',         # http://localhost:8080/sdvms/[VMNAME]/stop                     GET
    66     '/sdvms/(.*)',                      'os_sdvm',              # http://localhost:8080/sdvms/[VMNAME]                          GET, DELETE
    67     '/setup',                           'os_setup',             # http://localhost:8080/setup                                   GET
    68     '/vms',                             'os_vms',               # http://localhost:8080/vms                                     GET
    69     '/vms/(.*)',                        'os_vm',                # http://localhost:8080/vms/[VMNAME]                            GET
    70     '/update_template',                 'os_update_template',   # http://localhost:8080/update_template                         GET
    71     '/terminate',                       'os_terminate',         # http://localhost:8080/terminate                               GET
    72     '/',                                'os_root'               # http://localhost:8080/                                        GET
    73 )
    74 
    75 
    76 # ------------------------------------------------------------
    77 # vars
    78 
    79 # Global VMManager instance
    80 gvm_mgr = None
    81 
    82 
    83 # ------------------------------------------------------------
    84 # code
    85 
    86 
    87 class os_browsing:
    88     """OpenSecurity '/browsing' handler
    89     
    90     - GET: Start and prepare a new SecurityVM for Internet Browsing. Return the name of the VM.
    91     """
    92     
    93     def GET(self):
    94         log_call(web.ctx.environ)
    95         global gvm_mgr
    96         try:
    97             result = gvm_mgr.handleBrowsingRequest()
    98             return result
    99         except:
   100             raise web.internalerror()
   101 
   102        
   103 class os_fetch_image:
   104     """OpenSecurity '/fetch_initial_image' handler
   105     
   106     - GET: fetch the initial image from the X-Net Servers
   107             The initial image is stored in the
   108             Virtual Box default machine path.
   109             The result to this call is a temprary file
   110             which shows the progress (or error state)
   111             of this call.
   112     """
   113     
   114     def GET(self):
   115         
   116         log_call(web.ctx.environ)
   117         global gvm_mgr
   118 
   119         trace_file_name = os.path.join(tempfile.gettempdir(), 'OpenSecurity_fetch_image.log')
   120         trace_file = open(trace_file_name, 'w+')
   121 
   122         machine_folder = Cygwin.cygPath(gvm_mgr.getMachineFolder()) 
   123         download_initial_image_script = '/OpenSecurity/bin/download_initial_image.sh \'' + machine_folder + '\''
   124         Cygwin.bashExecute(download_initial_image_script, wait_return = False, stdout = trace_file, stderr = trace_file) 
   125 
   126         page = """
   127         <html>
   128         <head></head>
   129         <body>
   130         Fetch OpenSecurity image log ({0}):<br/>
   131         <iframe src="file://{0}" width="100%" height="100%"></iframe>
   132         </body>
   133         </head>
   134         """
   135         return page.format(trace_file_name)
   136 
   137 
   138 class os_init:
   139     """OpenSecurity '/init' handler
   140     
   141     - GET: Do initial import of OsecVM.ova
   142     """
   143     
   144     def GET(self):
   145         log_call(web.ctx.environ)
   146         global gvm_mgr
   147 
   148         trace_file_name = os.path.join(tempfile.gettempdir(), 'OpenSecurity_initial_import.log')
   149         trace_file = open(trace_file_name, 'w+')
   150 
   151         vm_image = Cygwin.cygPath(gvm_mgr.getMachineFolder()) + '/OsecVM.ova'
   152         initial_import_script = '/OpenSecurity/bin/initial_vm.sh \'' + vm_image + '\''
   153         Cygwin.bashExecute(initial_import_script, wait_return = False, stdout = trace_file, stderr = trace_file) 
   154 
   155         page = """
   156         <html>
   157         <head></head>
   158         <body>
   159         Import initial OpenSecurity image log ({0}):<br/>
   160         <iframe src="file://{0}" width="100%" height="100%"></iframe>
   161         </body>
   162         </head>
   163         """
   164         return page.format(trace_file_name)
   165 
   166 
   167 class os_root:
   168     """OpenSecurity '/' handler
   169     
   170     - GET: give information about current installation.
   171     """
   172     
   173     def GET(self):
   174         log_call(web.ctx.environ)
   175         global gvm_mgr
   176         res = "'os_server': { "
   177         res += "'version': '" + __version__ + "', "
   178         res += "'virtual box systemproperties': '" + str(gvm_mgr.systemProperties) + "', "
   179         res += "'current temporary folder': '" + tempfile.gettempdir() + "' "
   180         res += "}"
   181         return res
   182 
   183 
   184 class os_sdvm:
   185     """OpenSecurity '/sdvms/[VM]' handler
   186     
   187     - GET: Information about a specific SecurityVM
   188     - DELETE: Remove a specific
   189     """
   190     
   191     def GET(self, name):
   192         log_call(web.ctx.environ)
   193         global gvm_mgr
   194         return gvm_mgr.getVMInfo(name)
   195 
   196     def DELETE(self, name):
   197         log_call(web.ctx.environ)
   198         global gvm_mgr
   199         return gvm_mgr.removeVM(name)
   200             
   201 
   202 class os_sdvm_application:
   203     """OpenSecurity '/sdvms/[VM]/application/[CMD]' handler
   204     
   205     - GET: start application with given command in the VM.
   206     """
   207     
   208     def GET(self, name, command):
   209         log_call(web.ctx.environ)
   210         global gvm_mgr
   211         command = '/' + command
   212         result = Cygwin.sshExecuteX11(command, gvm_mgr.getHostOnlyIP(name), 'osecuser', Cygwin.cygPath(gvm_mgr.getMachineFolder()) + '/' + name + '/dvm_key'  )
   213         self.poweroffVM(name)
   214         return gvm_mgr.removeVM(name)
   215     
   216 
   217 class os_sdvm_ip:
   218     """OpenSecurity '/sdvms/[VM]/ip' handler
   219     
   220     - GET: give IP of SecurityVM.
   221     """
   222     
   223     def GET(self, name):
   224         log_call(web.ctx.environ)
   225         global gvm_mgr
   226         return gvm_mgr.getHostOnlyIP(name)
   227             
   228 
   229 class os_sdvm_start:
   230     """OpenSecurity '/sdvms/[VM]/start' handler
   231     
   232     - GET: Start specific SecuirtyVM.
   233     """
   234     
   235     def GET(self, name):
   236         log_call(web.ctx.environ)
   237         global gvm_mgr
   238         return gvm_mgr.startVM(name)
   239             
   240 
   241 class os_sdvm_stop:
   242     """OpenSecurity '/sdvms/[VM]/stop' handler
   243     
   244     - GET: stop specific Secuirty VM.
   245     """
   246     
   247     def GET(self, name):
   248         log_call(web.ctx.environ)
   249         global gvm_mgr
   250         return gvm_mgr.stopVM(name)
   251             
   252 
   253 class os_sdvms:
   254     """OpenSecurity '/sdvms' handler
   255     
   256     - GET: list all available secuirty VMs.
   257     - POST: create new security vm.
   258     """
   259     
   260     def GET(self):
   261         """get the list of SDVMs"""
   262         log_call(web.ctx.environ)
   263         global gvm_mgr
   264         return gvm_mgr.listSDVM() 
   265             
   266     def POST(self):
   267         """create a new SDVM"""
   268         log_call(web.ctx.environ)
   269         global gvm_mgr
   270         
   271         # get a new vm-name
   272         name = gvm_mgr.generateSDVMName()
   273         try:
   274             gvm_mgr.createVM(name)
   275         except:
   276             raise web.internalerror()
   277             
   278         return name
   279             
   280 
   281 class os_setup:
   282     """OpenSecurity '/setup' handler
   283     
   284     - GET: Give user some info how to setup the OpenSecurity envvironment
   285     """
   286     
   287     def GET(self):
   288 
   289         log_call(web.ctx.environ)
   290 
   291         page = """
   292         <html>
   293         <body>
   294         <h1>Setup OpenSecurity</h1>
   295         In order to setup OpenSecurity an inital VM image has to be downloaded and imported:<br/>
   296         <ul>
   297             <li>Download initial VM image: <a href="/fetch_initial_image">fetch_initial_image</a>
   298             <li>Import initial VM: <a href="/init">init</a>
   299         </ul>
   300         </body>
   301         </html>
   302         """
   303         return page
   304 
   305 
   306 class os_terminate:
   307     """OpenSecurity '/terminate' handler
   308     
   309     - GET: terminate the opensecurityd.
   310 
   311     YES: this here is bonkers. But the web.py http
   312     server runs infinite until a SystemExit exception
   313     or KeyboardInterrupt exception is raised.
   314 
   315     see: site-packages/web/httpserver.py - line 157ff
   316     see: site-packages/web/wsgiserver/__init__.py - line 1682ff
   317 
   318     So, we invoke a sys.exit(0) here to trigger server.stop().
   319 
   320     TODO: need to find a better way doing this, and not via the
   321           REST api. Maybe hack web.py server code?
   322     """
   323     
   324     def GET(self):
   325         log_call(web.ctx.environ)
   326         global gvm_mgr
   327         gvm_mgr.stop()
   328         gvm_mgr.cleanup()
   329         sys.exit(0)
   330         return None
   331 
   332 
   333 class os_update_template:
   334     """OpenSecurity '/update_template' handler
   335     
   336     - GET: update template vm
   337     """
   338     
   339     def GET(self):
   340         #return gvm_mgr.guestExecute('SecurityDVM', 'sudo apt-get -y update')
   341         global gvm_mgr
   342         log_call(web.ctx.environ)
   343         return gvm_mgr.updateTemplate()
   344 
   345 
   346 class os_vm:
   347     """OpenSecurity '/vms/[VM]' handler
   348     
   349     - GET: list information of arbitrary VM.
   350     """
   351     
   352     def GET(self, name):
   353         log_call(web.ctx.environ)
   354         global gvm_mgr
   355         return gvm_mgr.getVMInfo(name)
   356             
   357 
   358 class os_vms:
   359     """OpenSecurity '/vms' handler
   360     
   361     - GET: list all (also non Security) VMs.
   362     """
   363     
   364     def GET(self):
   365         log_call(web.ctx.environ)
   366         global gvm_mgr
   367         return gvm_mgr.listVM() 
   368             
   369 
   370 def log_call(web_environ):
   371     """log the incoming call to the REST api"""
   372     try:
   373         call = 'REST ' +  web_environ['REQUEST_METHOD'] + ' ' + web_environ['REQUEST_URI'] + ' from ' + web_environ['REMOTE_ADDR'] + ':' + web_environ['REMOTE_PORT']
   374         logger.debug(call)
   375     except:
   376         pass
   377 
   378 
   379 def main():
   380     """main startup for the opensecuirityd"""
   381 
   382     logger.debug('Starting OpenSecurity REST server')
   383 
   384     # ensure a VMManger is yet loaded
   385     global gvm_mgr
   386     gvm_mgr = vmmanager.VMManager.getInstance()
   387     
   388     # tweak sys.argv to control wep.py server start behavior
   389     sys.argv = [__file__, "8080"]
   390     server = web.application(opensecurity_urls, globals(), autoreload = False)
   391     server.run()
   392     
   393     logger.debug('Stopped OpenSecurity REST server')
   394 
   395 
   396 def stop():
   397     """stop the opensecuirityd"""
   398 
   399     # calling sys.exit() raises a SystemExit exception
   400     # of the WSGI Server to let it wind down
   401     # gracefully
   402     sys.exit(0)
   403 
   404 
   405 
   406 # start
   407 if __name__ == "__main__":
   408     main()
   409