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