1.1 --- a/OpenSecurity/bin/opensecurity_client_restful_server.py Thu Apr 24 12:19:30 2014 +0200
1.2 +++ b/OpenSecurity/bin/opensecurity_client_restful_server.py Tue Apr 29 13:00:46 2014 +0200
1.3 @@ -32,6 +32,7 @@
1.4 # ------------------------------------------------------------
1.5 # imports
1.6
1.7 +import json
1.8 import os
1.9 import os.path
1.10 import subprocess
1.11 @@ -44,7 +45,6 @@
1.12
1.13 # local
1.14 from environment import Environment
1.15 -from notification import Notification
1.16
1.17
1.18 # ------------------------------------------------------------
1.19 @@ -56,8 +56,8 @@
1.20
1.21 """All the URLs we know mapping to class handler"""
1.22 opensecurity_urls = (
1.23 - #'/application', 'os_application',
1.24 '/credentials', 'os_credentials',
1.25 + '/keyfile', 'os_keyfile',
1.26 '/notification', 'os_notification',
1.27 '/password', 'os_password',
1.28 '/', 'os_root'
1.29 @@ -68,56 +68,8 @@
1.30 # code
1.31
1.32
1.33 -# class os_application:
1.34 -#
1.35 -# PRESUMLY DEAD CODE
1.36 -#
1.37 - # """OpenSecurity '/application' handler.
1.38 -
1.39 - # This is called on GET /application?vm=VM-ID&app=APP-ID
1.40 - # This tries to access the vm identified with the label VM-ID
1.41 - # and launched the application identified APP-ID
1.42 - # """
1.43 -
1.44 - # def GET(self):
1.45 -
1.46 - # # pick the arguments
1.47 - # args = web.input()
1.48 -
1.49 - # # we _need_ a vm
1.50 - # if not "vm" in args:
1.51 - # raise web.badrequest('no vm given')
1.52 -
1.53 - # # we _need_ a app
1.54 - # if not "command" in args:
1.55 - # raise web.badrequest('no app given')
1.56 -
1.57 - # # check if we do have valid vm
1.58 - # v = [v for v in vms if v['name'] == args.vm]
1.59 - # if len(v) == 0:
1.60 - # raise web.notfound('vm not found')
1.61 - # v = v[0]
1.62 -
1.63 - # # check if we do have a valid app
1.64 - # a = [a for a in apps if a['name'] == args.app]
1.65 - # if len(a) == 0:
1.66 - # raise web.notfound('app not found')
1.67 - # a = a[0]
1.68 -
1.69 - # # invoke launch with
1.70 - # res = "starting: launch " + v['user'] + " " + v['ip'] + " " + a['command']
1.71 +class os_credentials:
1.72
1.73 - # launch_image = os.path.join(sys.path[0], 'launch.py')
1.74 - # process_command = [sys.executable, launch_image, v['user'], v['ip'], a['command']]
1.75 - # process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
1.76 - # result = process.communicate()[0]
1.77 - # if process.returncode != 0:
1.78 - # return 'Launch of application aborted.'
1.79 -
1.80 - # return result
1.81 -
1.82 -
1.83 -class os_credentials:
1.84 """OpenSecurity '/credentials' handler.
1.85
1.86 This is called on GET /credentials?text=TEXT.
1.87 @@ -134,18 +86,56 @@
1.88 if not "text" in args:
1.89 raise web.badrequest('no text given')
1.90
1.91 - # invoke the user dialog as a subprocess
1.92 - dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
1.93 + # remember remote ip
1.94 + remote_ip = web.ctx.environ['REMOTE_ADDR']
1.95 +
1.96 + # create the process which queries the user
1.97 + dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.pyw')
1.98 process_command = [sys.executable, dlg_image, 'credentials', args.text]
1.99 - process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
1.100 - result = process.communicate()[0]
1.101 - if process.returncode != 0:
1.102 - return 'Credentials request has been aborted.'
1.103 + process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
1.104
1.105 - return result
1.106 + # run process result handling in seprate thread (not to block main one)
1.107 + bouncer = UserResultBouncer(process, remote_ip, '/credentials')
1.108 + bouncer.start()
1.109 +
1.110 + return 'user queried for credentials'
1.111 +
1.112 +
1.113 +class os_keyfile:
1.114 +
1.115 + """OpenSecurity '/keyfile' handler.
1.116 +
1.117 + This is called on GET /keyfile?text=TEXT.
1.118 + Ideally this should pop up a user dialog to insert his
1.119 + password along with a keyfile.
1.120 + """
1.121 +
1.122 + def GET(self):
1.123 +
1.124 + # pick the arguments
1.125 + args = web.input()
1.126 +
1.127 + # we _need_ a text
1.128 + if not "text" in args:
1.129 + raise web.badrequest('no text given')
1.130 +
1.131 + # remember remote ip
1.132 + remote_ip = web.ctx.environ['REMOTE_ADDR']
1.133 +
1.134 + # create the process which queries the user
1.135 + dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.pyw')
1.136 + process_command = [sys.executable, dlg_image, 'keyfile', args.text]
1.137 + process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
1.138 +
1.139 + # run process result handling in seprate thread (not to block main one)
1.140 + bouncer = UserResultBouncer(process, remote_ip, '/keyfile')
1.141 + bouncer.start()
1.142 +
1.143 + return 'user queried for password and keyfile'
1.144
1.145
1.146 class os_notification:
1.147 +
1.148 """OpenSecurity '/notification' handler.
1.149
1.150 This is called on GET /notification?msgtype=TYPE&text=TEXT.
1.151 @@ -157,14 +147,11 @@
1.152 # pick the arguments
1.153 args = web.input()
1.154
1.155 - if "message" in args:
1.156 - print args.message
1.157 -
1.158 # we _need_ a type
1.159 if not "msgtype" in args:
1.160 raise web.badrequest('no msgtype given')
1.161
1.162 - if not args.msgtype in Notification.TYPES:
1.163 + if not args.msgtype in ['information', 'warning', 'critical']:
1.164 raise web.badrequest('Unknown value for msgtype')
1.165
1.166 # we _need_ a text
1.167 @@ -175,47 +162,12 @@
1.168 dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
1.169 process_command = [sys.executable, dlg_image, 'notification-' + args.msgtype, args.text]
1.170 process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
1.171 +
1.172 return "Ok"
1.173
1.174 -class PasswordSender(threading.Thread):
1.175 - remote_ip = None
1.176 - args = None
1.177 - def __init__(self, remote_ip, args):
1.178 - threading.Thread.__init__(self)
1.179 - self.args = args
1.180 - self.remote_ip = remote_ip
1.181 -
1.182 - def stop(self):
1.183 - self.running = False
1.184 -
1.185 - def run(self):
1.186 - # invoke the user dialog as a subprocess
1.187 - dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
1.188 - process_command = [sys.executable, dlg_image, 'password', self.args.text]
1.189 - process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
1.190 - result = process.communicate()[0]
1.191 - if process.returncode != 0:
1.192 - print 'password request has been aborted.'
1.193 - return
1.194 -
1.195 - # all ok, tell send request back appropriate destination
1.196 - try:
1.197 - password = result.split(':')[1].split("'")[1]
1.198 - except:
1.199 - print 'error in password parsing'
1.200 - return
1.201 -
1.202 - url_addr = 'http://' + self.remote_ip + ':58080/password'
1.203 - url_data = urllib.urlencode({ 'password': password})
1.204 - url = url_addr + '?' + url_data
1.205 - req = urllib2.Request(url)
1.206 - try:
1.207 - res = urllib2.urlopen(req)
1.208 - except:
1.209 - print 'failed to contact: ' + url_addr
1.210 - return
1.211
1.212 class os_password:
1.213 +
1.214 """OpenSecurity '/password' handler.
1.215
1.216 This is called on GET /password?text=TEXT.
1.217 @@ -235,13 +187,20 @@
1.218 # remember remote ip
1.219 remote_ip = web.ctx.environ['REMOTE_ADDR']
1.220
1.221 - sender = PasswordSender(remote_ip, args)
1.222 - sender.start()
1.223 + # create the process which queries the user
1.224 + dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.pyw')
1.225 + process_command = [sys.executable, dlg_image, 'password', args.text]
1.226 + process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
1.227
1.228 - return 'password told'
1.229 + # run process result handling in seprate thread (not to block main one)
1.230 + bouncer = UserResultBouncer(process, remote_ip, '/password')
1.231 + bouncer.start()
1.232 +
1.233 + return 'user queried for password'
1.234
1.235
1.236 class os_root:
1.237 +
1.238 """OpenSecurity '/' handler"""
1.239
1.240 def GET(self):
1.241 @@ -271,6 +230,15 @@
1.242 NOTE: check yout taskbar, the dialog window may not pop up in front of your browser window.
1.243
1.244
1.245 +Request a combination of password and keyfile:
1.246 + (copy paste this into your browser's address field after the host:port)
1.247 +
1.248 + /keyfile?text=Your%20private%20RSA%20Keyfile%3A
1.249 +
1.250 + (eg.: http://127.0.0.1:8090//keyfile?text=Your%20private%20RSA%20Keyfile%3A)
1.251 + NOTE: check yout taskbar, the dialog window may not pop up in front of your browser window.
1.252 +
1.253 +
1.254 Start a Browser:
1.255 (copy paste this into your browser's address field after the host:port)
1.256
1.257 @@ -282,7 +250,57 @@
1.258 return res
1.259
1.260
1.261 +class UserResultBouncer(threading.Thread):
1.262 +
1.263 + """A class to spawn off user I/O waiting and push the data back to the requesting services."""
1.264 +
1.265 + def __init__(self, process, remote_ip, resource):
1.266 +
1.267 + """ctor"""
1.268 +
1.269 + threading.Thread.__init__(self)
1.270 + self._process = process
1.271 + self._remote_ip = remote_ip
1.272 + self._resource = resource
1.273 +
1.274 +
1.275 + def stop(self):
1.276 +
1.277 + """stop thread"""
1.278 + self.running = False
1.279 +
1.280 +
1.281 + def run(self):
1.282 +
1.283 + """run the thread"""
1.284 +
1.285 + # invoke the user dialog as a subprocess
1.286 + result = self._process.communicate()[0]
1.287 + if self._process.returncode != 0:
1.288 + print 'user request has been aborted.'
1.289 + return
1.290 +
1.291 + # all ok, tell send request back appropriate destination
1.292 + try:
1.293 + j = json.loads(result)
1.294 + except:
1.295 + print 'error in password parsing'
1.296 + return
1.297 +
1.298 + # TODO: it would be WAY easier and secure if we just
1.299 + # add the result json to a HTTP-POST here.
1.300 + url_addr = 'http://' + self._remote_ip + ':58080' + self._resource
1.301 + url = url_addr + '?' + urllib.urlencode(j)
1.302 + req = urllib2.Request(url)
1.303 + try:
1.304 + res = urllib2.urlopen(req)
1.305 + except:
1.306 + print 'failed to contact: ' + url_addr
1.307 + return
1.308 +
1.309 +
1.310 # start
1.311 if __name__ == "__main__":
1.312 server = web.application(opensecurity_urls, globals())
1.313 server.run()
1.314 +