From 005d49d2f092039660a44896217a5c245dcc4685 Mon Sep 17 00:00:00 2001 From: Vincent Untz Date: Tue, 17 Nov 2015 17:47:56 +0100 Subject: [PATCH] Ensure metadata agent doesn't use SSL for UNIX socket The communication between the ns metadata proxy and the metadata agent is pure HTTP, and should not switch to HTTPS when neutron is using SSL. We're therefore telling wsgi.Server to forcefully disable SSL in that case. Change-Id: I2cb9fa231193bcd5c721c4d5cf0eb9c16e842349 Closes-Bug: #1514424 (cherry picked from commit 7a306e2918775ebb94d9e1408aaa2b7c3ed26fc6) --- neutron/agent/linux/utils.py | 2 +- neutron/tests/unit/test_wsgi.py | 22 ++++++++++++++++++++++ neutron/wsgi.py | 12 +++++++----- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/neutron/agent/linux/utils.py b/neutron/agent/linux/utils.py index 3166f1163f3..211177c390a 100644 --- a/neutron/agent/linux/utils.py +++ b/neutron/agent/linux/utils.py @@ -392,7 +392,7 @@ class UnixDomainWSGIServer(wsgi.Server): self._socket = None self._launcher = None self._server = None - super(UnixDomainWSGIServer, self).__init__(name) + super(UnixDomainWSGIServer, self).__init__(name, disable_ssl=True) def start(self, application, file_socket, workers, backlog, mode=None): self._socket = eventlet.listen(file_socket, diff --git a/neutron/tests/unit/test_wsgi.py b/neutron/tests/unit/test_wsgi.py index ff6515e2214..73076224159 100644 --- a/neutron/tests/unit/test_wsgi.py +++ b/neutron/tests/unit/test_wsgi.py @@ -175,6 +175,28 @@ class TestWSGIServer(base.BaseTestCase): server.stop() + def test_disable_ssl(self): + CONF.set_default('use_ssl', True) + + greetings = 'Hello, World!!!' + + def hello_world(env, start_response): + if env['PATH_INFO'] != '/': + start_response('404 Not Found', + [('Content-Type', 'text/plain')]) + return ['Not Found\r\n'] + start_response('200 OK', [('Content-Type', 'text/plain')]) + return [greetings] + + server = wsgi.Server("test_app", disable_ssl=True) + server.start(hello_world, 0, host="127.0.0.1") + + response = open_no_proxy('http://127.0.0.1:%d/' % server.port) + + self.assertEqual(greetings.encode('utf-8'), response.read()) + + server.stop() + @mock.patch.object(wsgi, 'eventlet') def test__run(self, eventlet_mock): server = wsgi.Server('test') diff --git a/neutron/wsgi.py b/neutron/wsgi.py index 8f349a926b7..5678c8d0244 100644 --- a/neutron/wsgi.py +++ b/neutron/wsgi.py @@ -76,9 +76,10 @@ def encode_body(body): class WorkerService(worker.NeutronWorker): """Wraps a worker to be handled by ProcessLauncher""" - def __init__(self, service, application): + def __init__(self, service, application, disable_ssl=False): self._service = service self._application = application + self._disable_ssl = disable_ssl self._server = None def start(self): @@ -89,7 +90,7 @@ class WorkerService(worker.NeutronWorker): # errors on service restart. # Duplicate a socket object to keep a file descriptor usable. dup_sock = self._service._socket.dup() - if CONF.use_ssl: + if CONF.use_ssl and not self._disable_ssl: dup_sock = sslutils.wrap(CONF, dup_sock) self._server = self._service.pool.spawn(self._service._run, self._application, @@ -112,10 +113,11 @@ class WorkerService(worker.NeutronWorker): class Server(object): """Server class to manage multiple WSGI sockets and applications.""" - def __init__(self, name, num_threads=1000): + def __init__(self, name, num_threads=1000, disable_ssl=False): # Raise the default from 8192 to accommodate large tokens eventlet.wsgi.MAX_HEADER_LINE = CONF.max_header_line self.num_threads = num_threads + self.disable_ssl = disable_ssl # Pool for a greenthread in which wsgi server will be running self.pool = eventlet.GreenPool(1) self.name = name @@ -123,7 +125,7 @@ class Server(object): # A value of 0 is converted to None because None is what causes the # wsgi server to wait forever. self.client_socket_timeout = CONF.client_socket_timeout or None - if CONF.use_ssl: + if CONF.use_ssl and not self.disable_ssl: sslutils.is_enabled(CONF) def _get_socket(self, host, port, backlog): @@ -186,7 +188,7 @@ class Server(object): self._launch(application, workers) def _launch(self, application, workers=0): - service = WorkerService(self, application) + service = WorkerService(self, application, self.disable_ssl) if workers < 1: # The API service should run in the current process. self._server = service