OpenSecurity/bin/opensecurity_client_restful_server.py
author om
Tue, 10 Dec 2013 14:04:11 +0100
changeset 31 d95fe93d7a83
parent 29 3f564e1673bb
child 46 f659d8fb57a8
permissions -rwxr-xr-x
opensecurityd can now invoke applications on vm
     1 #!/bin/env python
     2 # -*- coding: utf-8 -*-
     3 
     4 # ------------------------------------------------------------
     5 # opensecurity_client_restful_server
     6 # 
     7 # the OpenSecurity client 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 urllib
    40 import urllib2
    41 import web
    42 
    43 # local
    44 from environment import Environment
    45 from notification import Notification
    46 import opensecurity_server
    47 
    48 
    49 # ------------------------------------------------------------
    50 # const
    51 
    52 
    53 __version__ = "0.2"
    54 
    55 
    56 """All the URLs we know mapping to class handler"""
    57 opensecurity_urls = (
    58     #'/application',             'os_application',
    59     '/credentials',             'os_credentials',
    60     '/notification',            'os_notification',
    61     '/password',                'os_password',
    62     '/',                        'os_root'
    63 )
    64 
    65 
    66 # ------------------------------------------------------------
    67 # code
    68 
    69 
    70 # class os_application:
    71 #
    72 # PRESUMLY DEAD CODE
    73 #
    74     # """OpenSecurity '/application' handler.
    75     
    76     # This is called on GET /application?vm=VM-ID&app=APP-ID
    77     # This tries to access the vm identified with the label VM-ID
    78     # and launched the application identified APP-ID
    79     # """
    80     
    81     # def GET(self):
    82         
    83         # # pick the arguments
    84         # args = web.input()
    85         
    86         # # we _need_ a vm
    87         # if not "vm" in args:
    88             # raise web.badrequest('no vm given')
    89         
    90         # # we _need_ a app
    91         # if not "command" in args:
    92             # raise web.badrequest('no app given')
    93         
    94         # # check if we do have valid vm
    95         # v = [v for v in vms if v['name'] == args.vm]
    96         # if len(v) == 0:
    97             # raise web.notfound('vm not found')
    98         # v = v[0]
    99         
   100         # # check if we do have a valid app
   101         # a = [a for a in apps if a['name'] == args.app]
   102         # if len(a) == 0:
   103             # raise web.notfound('app not found')
   104         # a = a[0]
   105         
   106         # # invoke launch with 
   107         # res = "starting: launch " + v['user'] + " " + v['ip'] + " " + a['command']
   108 
   109         # launch_image = os.path.join(sys.path[0], 'launch.py')
   110         # process_command = [sys.executable, launch_image, v['user'], v['ip'], a['command']]
   111         # process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
   112         # result = process.communicate()[0]
   113         # if process.returncode != 0:
   114             # return 'Launch of application aborted.'
   115         
   116         # return result
   117         
   118 
   119 class os_credentials:
   120     """OpenSecurity '/credentials' handler.
   121     
   122     This is called on GET /credentials?text=TEXT.
   123     Ideally this should pop up a user dialog to insert his
   124     credentials based the given TEXT.
   125     """
   126     
   127     def GET(self):
   128         
   129         # pick the arguments
   130         args = web.input()
   131         
   132         # we _need_ a text
   133         if not "text" in args:
   134             raise web.badrequest('no text given')
   135         
   136         # invoke the user dialog as a subprocess
   137         dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
   138         process_command = [sys.executable, dlg_image, 'credentials', args.text]
   139         process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
   140         result = process.communicate()[0]
   141         if process.returncode != 0:
   142             return 'Credentials request has been aborted.'
   143         
   144         return result
   145 
   146 
   147 class os_notification:
   148     """OpenSecurity '/notification' handler.
   149     
   150     This is called on GET /notification?msgtype=TYPE&text=TEXT.
   151     This will pop up an OpenSecurity notifcation window
   152     """
   153     
   154     def GET(self):
   155         
   156         # pick the arguments
   157         args = web.input()
   158         
   159         # we _need_ a type
   160         if not "msgtype" in args:
   161             raise web.badrequest('no msgtype given')
   162             
   163         if not args.msgtype in Notification.TYPES:
   164             raise web.badrequest('Unknown value for msgtype')
   165             
   166         # we _need_ a text
   167         if not "text" in args:
   168             raise web.badrequest('no text given')
   169             
   170         # invoke the user dialog as a subprocess
   171         dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
   172         process_command = [sys.executable, dlg_image, 'notification-' + args.msgtype, args.text]
   173         process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
   174         return "Ok"
   175 
   176 
   177 class os_password:
   178     """OpenSecurity '/password' handler.
   179     
   180     This is called on GET /password?text=TEXT.
   181     Ideally this should pop up a user dialog to insert his
   182     password based device name.
   183     """
   184     
   185     def GET(self):
   186         
   187         # pick the arguments
   188         args = web.input()
   189         
   190         # we _need_ a text
   191         if not "text" in args:
   192             raise web.badrequest('no text given')
   193             
   194         # remember remote ip
   195         remote_ip = web.ctx.environ['REMOTE_ADDR']
   196         
   197         # invoke the user dialog as a subprocess
   198         dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
   199         process_command = [sys.executable, dlg_image, 'password', args.text]
   200         process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
   201         result = process.communicate()[0]
   202         if process.returncode != 0:
   203             return 'password request has been aborted.'
   204         
   205         # all ok, tell send request back appropriate destination
   206         
   207         # the returned value of the dialog is a jason object like
   208         # "{ 'password': 'THE_PASSWORD' }"
   209         # so we _could_ call eval(...) on this.
   210         #
   211         # However, anyone malicious enough _could_ encode a certain
   212         # "password" making some nasty things within that eval code. :(
   213         #
   214         # So this is plain old-school string hacking then ...
   215         try:
   216             password = result.split(':')[1].split("'")[1]
   217         except:
   218             raise web.internalerror('error in password parsing')
   219         
   220         url_addr = 'http://' + remote_ip + ':58080/password'
   221         url_data = urllib.urlencode({ 'password': password})
   222         req = urllib2.Request(url = url_addr + '?' + url_data)
   223         try:
   224             res = urllib2.urlopen(req)
   225         except:
   226             raise web.internalerror('failed to contact: ' + url_addr)
   227         
   228         return 'password told'
   229 
   230 
   231 class os_root:
   232     """OpenSecurity '/' handler"""
   233     
   234     def GET(self):
   235     
   236         res = "OpenSecurity-Client RESTFul Server { \"version\": \"%s\" }" % __version__
   237         
   238         # add some sample links
   239         res = res + """
   240         
   241 USAGE EXAMPLES:
   242         
   243 Request a password: 
   244     (copy paste this into your browser's address field after the host:port)
   245     
   246     /password?text=Give+me+a+password+for+device+%22My+USB+Drive%22+(ID%3A+32090-AAA-X0)
   247     
   248     (eg.: http://127.0.0.1:8090/password?text=Give+me+a+password+for+device+%22My+USB+Drive%22+(ID%3A+32090-AAA-X0))
   249     NOTE: check yout taskbar, the dialog window may not pop up in front of your browser window.
   250     
   251     
   252 Request a combination of user and password:
   253     (copy paste this into your browser's address field after the host:port)
   254     
   255     /credentials?text=Tell+the+NSA+which+credentials+to+use+in+order+to+avoid+hacking+noise+on+wire.
   256     
   257     (eg.: http://127.0.0.1:8090/credentials?text=Tell+the+NSA+which+credentials+to+use+in+order+to+avoid+hacking+noise+on+wire.)
   258     NOTE: check yout taskbar, the dialog window may not pop up in front of your browser window.
   259     
   260 
   261 Start a Browser:
   262     (copy paste this into your browser's address field after the host:port)
   263 
   264     /application?vm=Debian+7&app=Browser
   265 
   266     (e.g. http://127.0.0.1:8090/application?vm=Debian+7&app=Browser)
   267         """
   268     
   269         return res
   270 
   271 
   272 # start
   273 if __name__ == "__main__":
   274     server = web.application(opensecurity_urls, globals())
   275     server.run()