summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Young <sleepsonthefloor@gmail.com>2012-04-03 10:08:41 -0700
committerAnthony Young <sleepsonthefloor@gmail.com>2012-04-03 10:17:47 -0700
commit4c75210a4d8946cfc35db1d18150cfab72cba61e (patch)
tree288c0f7148fb25cf5a9b74858d2c07c3a96868b9
parentf84504bc63183b43cf60b1e02c871cc8fd9ee9c6 (diff)
downloadnovnc-4c75210a4d8946cfc35db1d18150cfab72cba61e.tar.gz
Add nova-novncproxy
* Adds the nova-novncproxy binary, to provide support for vnc + OpensStack nova * Adds the ability to pass an auth token in via url, which is subsequently passed back to the proxy as a cookie.
-rwxr-xr-xutils/nova-novncproxy148
-rw-r--r--vnc_auto.html13
2 files changed, 158 insertions, 3 deletions
diff --git a/utils/nova-novncproxy b/utils/nova-novncproxy
new file mode 100755
index 0000000..44d9292
--- /dev/null
+++ b/utils/nova-novncproxy
@@ -0,0 +1,148 @@
+#!/usr/bin/env python
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2012 Openstack, LLC.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#!/usr/bin/env python
+
+'''
+Websocket proxy that is compatible with Openstack Nova.
+Leverages wsproxy.py by Joel Martin
+'''
+
+import Cookie
+import socket
+import sys
+
+import wsproxy
+
+from nova import context
+from nova import flags
+from nova import rpc
+from nova import utils
+from nova.openstack.common import cfg
+
+
+opts = [
+ cfg.BoolOpt('record',
+ default=False,
+ help='Record sessions to FILE.[session_number]'),
+ cfg.BoolOpt('daemon',
+ default=False,
+ help='Become a daemon (background process)'),
+ cfg.BoolOpt('ssl_only',
+ default=False,
+ help='Disallow non-encrypted connections'),
+ cfg.BoolOpt('source_is_ipv6',
+ default=False,
+ help='Source is ipv6'),
+ cfg.StrOpt('cert',
+ default='self.pem',
+ help='SSL certificate file'),
+ cfg.StrOpt('key',
+ default=None,
+ help='SSL key file (if separate from cert)'),
+ cfg.StrOpt('web',
+ default='.',
+ help='Run webserver on same port. Serve files from DIR.'),
+ cfg.StrOpt('novncproxy_host',
+ default='0.0.0.0',
+ help='Host on which to listen for incoming requests'),
+ cfg.IntOpt('novncproxy_port',
+ default=6080,
+ help='Port on which to listen for incoming requests'),
+ ]
+FLAGS = flags.FLAGS
+FLAGS.register_cli_opts(opts)
+
+
+class NovaWebSocketProxy(wsproxy.WebSocketProxy):
+ def __init__(self, *args, **kwargs):
+ wsproxy.WebSocketProxy.__init__(self, *args, **kwargs)
+
+ def new_client(self):
+ """
+ Called after a new WebSocket connection has been established.
+ """
+ cookie = Cookie.SimpleCookie()
+ cookie.load(self.headers.getheader('cookie'))
+ token = cookie['token'].value
+ ctxt = context.get_admin_context()
+ connect_info = rpc.call(ctxt, 'consoleauth',
+ {'method': 'check_token',
+ 'args': {'token': token}})
+
+ if not connect_info:
+ raise Exception("Invalid Token")
+
+ host = connect_info['host']
+ port = int(connect_info['port'])
+
+ # Connect to the target
+ self.msg("connecting to: %s:%s" % (
+ host, port))
+ tsock = self.socket(host, port,
+ connect=True)
+
+ # Handshake as necessary
+ if connect_info.get('internal_access_path'):
+ tsock.send("CONNECT %s HTTP/1.1\r\n\r\n" %
+ connect_info['internal_access_path'])
+ while True:
+ data = tsock.recv(4096, socket.MSG_PEEK)
+ if data.find("\r\n\r\n") != -1:
+ if not data.split("\r\n")[0].find("200"):
+ raise Exception("Invalid Connection Info")
+ tsock.recv(len(data))
+ break
+
+ if self.verbose and not self.daemon:
+ print(self.traffic_legend)
+
+ # Start proxying
+ try:
+ self.do_proxy(tsock)
+ except:
+ if tsock:
+ tsock.shutdown(socket.SHUT_RDWR)
+ tsock.close()
+ self.vmsg("%s:%s: Target closed" % (host, port))
+ raise
+
+
+if __name__ == '__main__':
+ if FLAGS.ssl_only and not os.path.exists(FLAGS.cert):
+ parser.error("SSL only and %s not found" % FLAGS.cert)
+
+ # Setup flags
+ utils.default_flagfile()
+ FLAGS(sys.argv)
+
+ # Create and start the NovaWebSockets proxy
+ server = NovaWebSocketProxy(listen_host=FLAGS.novncproxy_host,
+ listen_port=FLAGS.novncproxy_port,
+ source_is_ipv6=FLAGS.source_is_ipv6,
+ verbose=FLAGS.verbose,
+ cert=FLAGS.cert,
+ key=FLAGS.key,
+ ssl_only=FLAGS.ssl_only,
+ daemon=FLAGS.daemon,
+ record=FLAGS.record,
+ web=FLAGS.web,
+ target_host='ignore',
+ target_port='ignore',
+ wrap_mode='exit',
+ wrap_cmd=None)
+ server.start_server()
diff --git a/vnc_auto.html b/vnc_auto.html
index 77df8bb..ffdfc00 100644
--- a/vnc_auto.html
+++ b/vnc_auto.html
@@ -84,14 +84,15 @@
}
window.onload = function () {
- var host, port, password, path;
+ var host, port, password, path, token;
$D('sendCtrlAltDelButton').style.display = "inline";
$D('sendCtrlAltDelButton').onclick = sendCtrlAltDel;
document.title = unescape(WebUtil.getQueryVar('title', 'noVNC'));
- host = WebUtil.getQueryVar('host', null);
- port = WebUtil.getQueryVar('port', null);
+ token = WebUtil.getQueryVar('token', null);
+ host = window.location.hostname;
+ port = window.location.port;
password = WebUtil.getQueryVar('password', '');
path = WebUtil.getQueryVar('path', 'websockify');
if ((!host) || (!port)) {
@@ -109,6 +110,12 @@
'view_only': WebUtil.getQueryVar('view_only', false),
'updateState': updateState,
'onPasswordRequired': passwordRequired});
+
+ /* If a token variable is passed in, set the parameter in a cookie. This is
+ used by nova-novncproxy. */
+ if (token) {
+ WebUtil.createCookie('token', token, 1)
+ }
rfb.connect(host, port, password, path);
};
</script>