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