summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnthony Young <sleepsonthefloor@gmail.com>2011-03-29 12:54:35 -0700
committerAnthony Young <sleepsonthefloor@gmail.com>2011-03-29 12:54:35 -0700
commit3e9b5977137c430d218ec8c00e286b691ea8367d (patch)
tree77bd941de12a767d692110eb04694cfac8e8d906
parent94092e3d896732fa1a97627f0fa504c3af70b3c5 (diff)
downloadnova-3e9b5977137c430d218ec8c00e286b691ea8367d.tar.gz
nova-3e9b5977137c430d218ec8c00e286b691ea8367d.tar.xz
nova-3e9b5977137c430d218ec8c00e286b691ea8367d.zip
use manager pattern for auth token proxy
-rwxr-xr-xbin/nova-vncproxy (renamed from bin/nova-vnc-proxy)31
-rw-r--r--doc/source/runnova/vncconsole.rst6
-rw-r--r--nova/flags.py2
-rw-r--r--nova/vnc/auth.py103
-rw-r--r--nova/vnc/proxy.py3
5 files changed, 85 insertions, 60 deletions
diff --git a/bin/nova-vnc-proxy b/bin/nova-vncproxy
index e26bc6d8c..0fad8397d 100755
--- a/bin/nova-vnc-proxy
+++ b/bin/nova-vncproxy
@@ -1,8 +1,7 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
-# Copyright 2010 United States Government as represented by the
-# Administrator of the National Aeronautics and Space Administration.
+# Copyright (c) 2010 Openstack, LLC.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -34,6 +33,7 @@ gettext.install('nova', unicode=1)
from nova import flags
from nova import log as logging
+from nova import service
from nova import utils
from nova import wsgi
from nova import version
@@ -45,16 +45,19 @@ LOG = logging.getLogger('nova.vnc-proxy')
FLAGS = flags.FLAGS
-flags.DEFINE_string('vnc_proxy_wwwroot', '/var/lib/nova/noVNC/',
+flags.DEFINE_string('vncproxy_wwwroot', '/var/lib/nova/noVNC/',
'Full path to noVNC directory')
flags.DEFINE_boolean('vnc_debug', False,
'Enable debugging features, like token bypassing')
-flags.DEFINE_integer('vnc_proxy_port', 6080,
+flags.DEFINE_integer('vncproxy_port', 6080,
'Port that the VNC proxy should bind to')
-flags.DEFINE_string('vnc_proxy_host', '0.0.0.0',
+flags.DEFINE_string('vncproxy_host', '0.0.0.0',
'Address that the VNC proxy should bind to')
flags.DEFINE_integer('vnc_token_ttl', 300,
'How many seconds before deleting tokens')
+flags.DEFINE_string('vncproxy_manager', 'nova.vnc.auth.VNCProxyAuthManager',
+ 'Manager for vncproxy auth')
+
flags.DEFINE_flag(flags.HelpFlag())
flags.DEFINE_flag(flags.HelpshortFlag())
flags.DEFINE_flag(flags.HelpXMLFlag())
@@ -68,18 +71,20 @@ if __name__ == "__main__":
LOG.audit(_("Starting nova-vnc-proxy node (version %s)"),
version.version_string_with_vcs())
- if not (os.path.exists(FLAGS.vnc_proxy_wwwroot) and
- os.path.exists(FLAGS.vnc_proxy_wwwroot + '/vnc_auto.html')):
- LOG.info(_("Missing vnc_proxy_wwwroot (version %s)"),
- FLAGS.vnc_proxy_wwwroot)
+ service.serve()
+
+ if not (os.path.exists(FLAGS.vncproxy_wwwroot) and
+ os.path.exists(FLAGS.vncproxy_wwwroot + '/vnc_auto.html')):
+ LOG.info(_("Missing vncproxy_wwwroot (version %s)"),
+ FLAGS.vncproxy_wwwroot)
LOG.info(_("You need a slightly modified version of noVNC "
"to work with the nova-vnc-proxy"))
LOG.info(_("Check out the most recent nova noVNC code: %s"),
"git://github.com/sleepsonthefloor/noVNC.git")
- LOG.info(_("And drop it in %s"), FLAGS.vnc_proxy_wwwroot)
+ LOG.info(_("And drop it in %s"), FLAGS.vncproxy_wwwroot)
exit(1)
- app = proxy.WebsocketVNCProxy(FLAGS.vnc_proxy_wwwroot)
+ app = proxy.WebsocketVNCProxy(FLAGS.vncproxy_wwwroot)
LOG.audit(_("Allowing access to the following files: %s"),
app.get_whitelist())
@@ -89,8 +94,8 @@ if __name__ == "__main__":
if FLAGS.vnc_debug:
with_auth = proxy.DebugMiddleware(with_logging)
else:
- with_auth = auth.NovaAuthMiddleware(with_logging)
+ with_auth = auth.VNCNovaAuthMiddleware(with_logging)
server = wsgi.Server()
- server.start(with_auth, FLAGS.vnc_proxy_port, host=FLAGS.vnc_proxy_host)
+ server.start(with_auth, FLAGS.vncproxy_port, host=FLAGS.vncproxy_host)
server.wait()
diff --git a/doc/source/runnova/vncconsole.rst b/doc/source/runnova/vncconsole.rst
index 69f147613..6d93bad93 100644
--- a/doc/source/runnova/vncconsole.rst
+++ b/doc/source/runnova/vncconsole.rst
@@ -40,14 +40,14 @@ you can at find git://github.com/sleepsonthefloor/noVNC.git.
.. todo:: add instruction for installing from package
-noVNC must be in the location specified by --vnc_proxy_wwwroot, which defaults
+noVNC must be in the location specified by --vncproxy_wwwroot, which defaults
to /var/lib/nova/noVNC. nova-vnc-proxy will fail to launch until this code
is properly installed.
By default, nova-vnc-proxy binds 0.0.0.0:6080. This can be configured with:
-* --vnc_proxy_port=[port]
-* --vnc_proxy_host=[host]
+* --vncproxy_port=[port]
+* --vncproxy_host=[host]
Enabling VNC Consoles in Nova
diff --git a/nova/flags.py b/nova/flags.py
index ba543f46d..b5c0cd380 100644
--- a/nova/flags.py
+++ b/nova/flags.py
@@ -281,7 +281,7 @@ DEFINE_string('ajax_console_proxy_url',
in the form "http://127.0.0.1:8000"')
DEFINE_string('ajax_console_proxy_port',
8000, 'port that ajax_console_proxy binds')
-DEFINE_string('vnc_console_proxy_topic', 'vnc_proxy',
+DEFINE_string('vnc_console_proxy_topic', 'vncproxy',
'the topic vnc proxy nodes listen on')
DEFINE_string('vnc_console_proxy_url',
'http://127.0.0.1:6080',
diff --git a/nova/vnc/auth.py b/nova/vnc/auth.py
index dff9b376f..105b68fe2 100644
--- a/nova/vnc/auth.py
+++ b/nova/vnc/auth.py
@@ -1,9 +1,7 @@
#!/usr/bin/env python
-# pylint: disable-msg=C0103
# vim: tabstop=4 shiftwidth=4 softtabstop=4
-# Copyright 2010 United States Government as represented by the
-# Administrator of the National Aeronautics and Space Administration.
+# Copyright (c) 2010 Openstack, LLC.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -26,8 +24,10 @@ import webob
from webob import Request
+from nova import context
from nova import flags
from nova import log as logging
+from nova import manager
from nova import rpc
from nova import utils
from nova import wsgi
@@ -38,12 +38,24 @@ LOG = logging.getLogger('nova.vnc-proxy')
FLAGS = flags.FLAGS
-class NovaAuthMiddleware(object):
+class VNCNovaAuthMiddleware(object):
"""Implementation of Middleware to Handle Nova Auth."""
def __init__(self, app):
self.app = app
- self.register_listeners()
+ self.token_cache = {}
+ utils.LoopingCall(self._delete_expired_tokens).start(1)
+
+ def get_token_info(self, token):
+ if token in self.token_cache:
+ return self.token_cache[token]
+
+ rval = rpc.call(context.get_admin_context(),
+ FLAGS.vnc_console_proxy_topic,
+ {"method": "check_token", "args": {'token': token}})
+ if rval:
+ self.token_cache[token] = rval
+ return rval
@webob.dec.wsgify
def __call__(self, req):
@@ -55,49 +67,27 @@ class NovaAuthMiddleware(object):
if 'token' in auth_params:
token = auth_params['token'][0]
- if not token in self.tokens:
+ connection_info = self.get_token_info(token)
+ if not connection_info:
LOG.audit(_("Unauthorized Access: (%s)"), req.environ)
return webob.exc.HTTPForbidden(detail='Unauthorized')
if req.path == vnc.proxy.WS_ENDPOINT:
- req.environ['vnc_host'] = self.tokens[token]['args']['host']
- req.environ['vnc_port'] = int(self.tokens[token]['args']['port'])
+ req.environ['vnc_host'] = connection_info['host']
+ req.environ['vnc_port'] = int(connection_info['port'])
return req.get_response(self.app)
- def register_listeners(self):
- middleware = self
- middleware.tokens = {}
-
- class TopicProxy():
- @staticmethod
- def authorize_vnc_console(context, **kwargs):
- data = kwargs
- token = kwargs['token']
- LOG.audit(_("Received Token: %s)"), token)
- middleware.tokens[token] = \
- {'args': kwargs, 'last_activity_at': time.time()}
-
- def delete_expired_tokens():
- now = time.time()
- to_delete = []
- for k, v in middleware.tokens.items():
- if now - v['last_activity_at'] > FLAGS.vnc_token_ttl:
- to_delete.append(k)
-
- for k in to_delete:
- LOG.audit(_("Deleting Token: %s)"), k)
- del middleware.tokens[k]
-
- conn = rpc.Connection.instance(new=True)
- consumer = rpc.TopicAdapterConsumer(
- connection=conn,
- proxy=TopicProxy,
- topic=FLAGS.vnc_console_proxy_topic)
-
- utils.LoopingCall(consumer.fetch,
- enable_callbacks=True).start(0.1)
- utils.LoopingCall(delete_expired_tokens).start(1)
+ def _delete_expired_tokens(self):
+ now = time.time()
+ to_delete = []
+ for k, v in self.token_cache.items():
+ if now - v['last_activity_at'] > FLAGS.vnc_token_ttl:
+ to_delete.append(k)
+
+ for k in to_delete:
+ del self.token_cache[k]
+
class LoggingMiddleware(object):
@@ -112,3 +102,34 @@ class LoggingMiddleware(object):
LOG.info(_("Received Request: %s"), req.url)
return req.get_response(self.app)
+
+
+class VNCProxyAuthManager(manager.Manager):
+ """Manages token based authentication."""
+
+ def __init__(self, scheduler_driver=None, *args, **kwargs):
+ super(VNCProxyAuthManager, self).__init__(*args, **kwargs)
+ self.tokens = {}
+ utils.LoopingCall(self._delete_expired_tokens).start(1)
+
+ def authorize_vnc_console(self, context, token, host, port):
+ self.tokens[token] = {'host': host,
+ 'port': port,
+ 'last_activity_at': time.time()}
+ LOG.audit(_("Received Token: %s, %s)"), token, self.tokens[token])
+
+ def check_token(self, context, token):
+ LOG.audit(_("Checking Token: %s, %s)"), token, (token in self.tokens))
+ if token in self.tokens:
+ return self.tokens[token]
+
+ def _delete_expired_tokens(self):
+ now = time.time()
+ to_delete = []
+ for k, v in self.tokens.items():
+ if now - v['last_activity_at'] > FLAGS.vnc_token_ttl:
+ to_delete.append(k)
+
+ for k in to_delete:
+ LOG.audit(_("Deleting Expired Token: %s)"), k)
+ del self.tokens[k]
diff --git a/nova/vnc/proxy.py b/nova/vnc/proxy.py
index 49379d9ae..c6e46396b 100644
--- a/nova/vnc/proxy.py
+++ b/nova/vnc/proxy.py
@@ -1,8 +1,7 @@
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
-# Copyright 2010 United States Government as represented by the
-# Administrator of the National Aeronautics and Space Administration.
+# Copyright (c) 2010 Openstack, LLC.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");