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