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