Support for SSL in wsgi.Server
SSL are entirely optional. Support for SSL as well using code from glance. We have some new options for configuring the SSL support. There are tests for accessing a sample app w/o ipv6 or ssl, one with just ssl and one with ipv6 and ssl DocImpact Change-Id: I9aa1db6c9563868bf68ced7c4311daa870216ced
This commit is contained in:
parent
b8fca650b4
commit
24d961023f
@ -19,16 +19,24 @@
|
|||||||
"""Unit tests for `cinder.wsgi`."""
|
"""Unit tests for `cinder.wsgi`."""
|
||||||
|
|
||||||
import os.path
|
import os.path
|
||||||
|
import ssl
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
import urllib2
|
||||||
|
import webob
|
||||||
import webob.dec
|
import webob.dec
|
||||||
|
|
||||||
from cinder.api.middleware import fault
|
from cinder.api.middleware import fault
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
|
from cinder.openstack.common import cfg
|
||||||
from cinder import test
|
from cinder import test
|
||||||
import cinder.wsgi
|
import cinder.wsgi
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
TEST_VAR_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||||
|
'var'))
|
||||||
|
|
||||||
|
|
||||||
class TestLoaderNothingExists(test.TestCase):
|
class TestLoaderNothingExists(test.TestCase):
|
||||||
"""Loader tests where os.path.exists always returns False."""
|
"""Loader tests where os.path.exists always returns False."""
|
||||||
@ -103,6 +111,68 @@ class TestWSGIServer(unittest.TestCase):
|
|||||||
server.stop()
|
server.stop()
|
||||||
server.wait()
|
server.wait()
|
||||||
|
|
||||||
|
def test_app(self):
|
||||||
|
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 = cinder.wsgi.Server("test_app", hello_world)
|
||||||
|
server.start()
|
||||||
|
|
||||||
|
response = urllib2.urlopen('http://127.0.0.1:%d/' % server.port)
|
||||||
|
self.assertEquals(greetings, response.read())
|
||||||
|
|
||||||
|
server.stop()
|
||||||
|
|
||||||
|
def test_app_using_ssl(self):
|
||||||
|
CONF.set_default("ssl_cert_file",
|
||||||
|
os.path.join(TEST_VAR_DIR, 'certificate.crt'))
|
||||||
|
CONF.set_default("ssl_key_file",
|
||||||
|
os.path.join(TEST_VAR_DIR, 'privatekey.key'))
|
||||||
|
|
||||||
|
greetings = 'Hello, World!!!'
|
||||||
|
|
||||||
|
@webob.dec.wsgify
|
||||||
|
def hello_world(req):
|
||||||
|
return greetings
|
||||||
|
|
||||||
|
server = cinder.wsgi.Server("test_app", hello_world)
|
||||||
|
server.start()
|
||||||
|
|
||||||
|
response = urllib2.urlopen('https://127.0.0.1:%d/' % server.port)
|
||||||
|
self.assertEquals(greetings, response.read())
|
||||||
|
|
||||||
|
server.stop()
|
||||||
|
|
||||||
|
def test_app_using_ipv6_and_ssl(self):
|
||||||
|
CONF.set_default("ssl_cert_file",
|
||||||
|
os.path.join(TEST_VAR_DIR, 'certificate.crt'))
|
||||||
|
CONF.set_default("ssl_key_file",
|
||||||
|
os.path.join(TEST_VAR_DIR, 'privatekey.key'))
|
||||||
|
|
||||||
|
greetings = 'Hello, World!!!'
|
||||||
|
|
||||||
|
@webob.dec.wsgify
|
||||||
|
def hello_world(req):
|
||||||
|
return greetings
|
||||||
|
|
||||||
|
server = cinder.wsgi.Server("test_app",
|
||||||
|
hello_world,
|
||||||
|
host="::1",
|
||||||
|
port=0)
|
||||||
|
server.start()
|
||||||
|
|
||||||
|
response = urllib2.urlopen('https://[::1]:%d/' % server.port)
|
||||||
|
self.assertEquals(greetings, response.read())
|
||||||
|
|
||||||
|
server.stop()
|
||||||
|
|
||||||
|
|
||||||
class ExceptionTest(test.TestCase):
|
class ExceptionTest(test.TestCase):
|
||||||
|
|
||||||
|
35
cinder/tests/var/ca.crt
Normal file
35
cinder/tests/var/ca.crt
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
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
|
||||||
|
WoRMgEwjGJWqzhJZUYpUAQ==
|
||||||
|
-----END CERTIFICATE-----
|
30
cinder/tests/var/certificate.crt
Normal file
30
cinder/tests/var/certificate.crt
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFLjCCAxYCAQEwDQYJKoZIhvcNAQEFBQAwYTELMAkGA1UEBhMCQVUxEzARBgNV
|
||||||
|
BAgTClNvbWUtU3RhdGUxFTATBgNVBAoTDE9wZW5zdGFjayBDQTESMBAGA1UECxMJ
|
||||||
|
R2xhbmNlIENBMRIwEAYDVQQDEwlHbGFuY2UgQ0EwHhcNMTIwMjA5MTcxMDUzWhcN
|
||||||
|
MjIwMjA2MTcxMDUzWjBZMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0
|
||||||
|
ZTESMBAGA1UEChMJT3BlbnN0YWNrMQ8wDQYDVQQLEwZHbGFuY2UxEDAOBgNVBAMT
|
||||||
|
BzAuMC4wLjAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXpUkQN6pu
|
||||||
|
avo+gz3o1K4krVdPl1m7NjNJDyD/+ZH0EGNcEN7iag1qPE7JsjqGPNZsQK1dMoXb
|
||||||
|
Sz+OSi9qvNeJnBcfwUx5qTAtwyAb9AxGkwuMafIU+lWbsclo+dPGsja01ywbXTCZ
|
||||||
|
bF32iqnpOMYhfxWUdoQYiBkhxxhW9eMPKLS/KkP8/bx+Vaa2XJiAebqkd9nrksAA
|
||||||
|
BeGc9mlafYBEmiChPdJEPw+1ePA4QVq9aPepDsqAKtGN8JLpmoC3BdxQQTbbwL3Q
|
||||||
|
8fTXK4tCNUaVk4AbDy/McFq6y0ocQoBPJjihOY35mWG/OLtcI99yPOpWGnps/5aG
|
||||||
|
/64DDJ2D67Fnaj6gKHV+6TXFO8KZxlnxtgtiZDJBZkneTBt9ArSOv+l6NBsumRz0
|
||||||
|
iEJ4o4H1S2TSMnprAvX7WnGtc6Xi9gXahYcDHEelwwYzqAiTBv6hxSp4MZ2dNXa+
|
||||||
|
KzOitC7ZbV2qsg0au0wjfE/oSQ3NvsvUr8nOmfutJTvHRAwbC1v4G/tuAsO7O0w2
|
||||||
|
0u2B3u+pG06m5+rnEqp+rB9hmukRYTfgEFRRsVIvpFl/cwvPXKRcX03UIMx+lLr9
|
||||||
|
Ft+ep7YooBhY3wY2kwCxD4lRYNmbwsCIVywZt40f/4ad98TkufR9NhsfycxGeqbr
|
||||||
|
mTMFlZ8TTlmP82iohekKCOvoyEuTIWL2+wIDAQABMA0GCSqGSIb3DQEBBQUAA4IC
|
||||||
|
AQBMUBgV0R+Qltf4Du7u/8IFmGAoKR/mktB7R1gRRAqsvecUt7kIwBexGdavGg1y
|
||||||
|
0pU0+lgUZjJ20N1SlPD8gkNHfXE1fL6fmMjWz4dtYJjzRVhpufHPeBW4tl8DgHPN
|
||||||
|
rBGAYQ+drDSXaEjiPQifuzKx8WS+DGA3ki4co5mPjVnVH1xvLIdFsk89z3b3YD1k
|
||||||
|
yCJ/a9K36x6Z/c67JK7s6MWtrdRF9+MVnRKJ2PK4xznd1kBz16V+RA466wBDdARY
|
||||||
|
vFbtkafbEqOb96QTonIZB7+fAldKDPZYnwPqasreLmaGOaM8sxtlPYAJ5bjDONbc
|
||||||
|
AaXG8BMRQyO4FyH237otDKlxPyHOFV66BaffF5S8OlwIMiZoIvq+IcTZOdtDUSW2
|
||||||
|
KHNLfe5QEDZdKjWCBrfqAfvNuG13m03WqfmcMHl3o/KiPJlx8l9Z4QEzZ9xcyQGL
|
||||||
|
cncgeHM9wJtzi2cD/rTDNFsx/gxvoyutRmno7I3NRbKmpsXF4StZioU3USRspB07
|
||||||
|
hYXOVnG3pS+PjVby7ThT3gvFHSocguOsxClx1epdUJAmJUbmM7NmOp5WVBVtMtC2
|
||||||
|
Su4NG/xJciXitKzw+btb7C7RjO6OEqv/1X/oBDzKBWQAwxUC+lqmnM7W6oqWJFEM
|
||||||
|
YfTLnrjs7Hj6ThMGcEnfvc46dWK3dz0RjsQzUxugPuEkLA==
|
||||||
|
-----END CERTIFICATE-----
|
51
cinder/tests/var/privatekey.key
Normal file
51
cinder/tests/var/privatekey.key
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
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
|
||||||
|
-----END RSA PRIVATE KEY-----
|
131
cinder/wsgi.py
131
cinder/wsgi.py
@ -19,8 +19,12 @@
|
|||||||
|
|
||||||
"""Utility methods for working with WSGI servers."""
|
"""Utility methods for working with WSGI servers."""
|
||||||
|
|
||||||
|
import errno
|
||||||
|
import os
|
||||||
import socket
|
import socket
|
||||||
|
import ssl
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
import eventlet
|
import eventlet
|
||||||
import eventlet.wsgi
|
import eventlet.wsgi
|
||||||
@ -32,9 +36,34 @@ import webob.exc
|
|||||||
|
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder import flags
|
from cinder import flags
|
||||||
|
from cinder.openstack.common import cfg
|
||||||
from cinder.openstack.common import log as logging
|
from cinder.openstack.common import log as logging
|
||||||
from cinder import utils
|
from cinder import utils
|
||||||
|
|
||||||
|
socket_opts = [
|
||||||
|
cfg.IntOpt('backlog',
|
||||||
|
default=4096,
|
||||||
|
help="Number of backlog requests to configure the socket with"),
|
||||||
|
cfg.IntOpt('tcp_keepidle',
|
||||||
|
default=600,
|
||||||
|
help="Sets the value of TCP_KEEPIDLE in seconds for each "
|
||||||
|
"server socket. Not supported on OS X."),
|
||||||
|
cfg.StrOpt('ssl_ca_file',
|
||||||
|
default=None,
|
||||||
|
help="CA certificate file to use to verify "
|
||||||
|
"connecting clients"),
|
||||||
|
cfg.StrOpt('ssl_cert_file',
|
||||||
|
default=None,
|
||||||
|
help="Certificate file to use when starting "
|
||||||
|
"the server securely"),
|
||||||
|
cfg.StrOpt('ssl_key_file',
|
||||||
|
default=None,
|
||||||
|
help="Private key file to use when starting "
|
||||||
|
"the server securely"),
|
||||||
|
]
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
CONF.register_opts(socket_opts)
|
||||||
|
|
||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
@ -68,6 +97,84 @@ class Server(object):
|
|||||||
self._logger = logging.getLogger("eventlet.wsgi.server")
|
self._logger = logging.getLogger("eventlet.wsgi.server")
|
||||||
self._wsgi_logger = logging.WritableLogger(self._logger)
|
self._wsgi_logger = logging.WritableLogger(self._logger)
|
||||||
|
|
||||||
|
def _get_socket(self, host, port, backlog):
|
||||||
|
bind_addr = (host, port)
|
||||||
|
# TODO(dims): eventlet's green dns/socket module does not actually
|
||||||
|
# support IPv6 in getaddrinfo(). We need to get around this in the
|
||||||
|
# future or monitor upstream for a fix
|
||||||
|
try:
|
||||||
|
info = socket.getaddrinfo(bind_addr[0],
|
||||||
|
bind_addr[1],
|
||||||
|
socket.AF_UNSPEC,
|
||||||
|
socket.SOCK_STREAM)[0]
|
||||||
|
family = info[0]
|
||||||
|
bind_addr = info[-1]
|
||||||
|
except Exception:
|
||||||
|
family = socket.AF_INET
|
||||||
|
|
||||||
|
cert_file = CONF.ssl_cert_file
|
||||||
|
key_file = CONF.ssl_key_file
|
||||||
|
ca_file = CONF.ssl_ca_file
|
||||||
|
use_ssl = cert_file or key_file
|
||||||
|
|
||||||
|
if cert_file and not os.path.exists(cert_file):
|
||||||
|
raise RuntimeError(_("Unable to find cert_file : %s") % cert_file)
|
||||||
|
|
||||||
|
if ca_file and not os.path.exists(ca_file):
|
||||||
|
raise RuntimeError(_("Unable to find ca_file : %s") % ca_file)
|
||||||
|
|
||||||
|
if key_file and not os.path.exists(key_file):
|
||||||
|
raise RuntimeError(_("Unable to find key_file : %s") % key_file)
|
||||||
|
|
||||||
|
if use_ssl and (not cert_file or not key_file):
|
||||||
|
raise RuntimeError(_("When running server in SSL mode, you must "
|
||||||
|
"specify both a cert_file and key_file "
|
||||||
|
"option value in your configuration file"))
|
||||||
|
|
||||||
|
def wrap_ssl(sock):
|
||||||
|
ssl_kwargs = {
|
||||||
|
'server_side': True,
|
||||||
|
'certfile': cert_file,
|
||||||
|
'keyfile': key_file,
|
||||||
|
'cert_reqs': ssl.CERT_NONE,
|
||||||
|
}
|
||||||
|
|
||||||
|
if CONF.ssl_ca_file:
|
||||||
|
ssl_kwargs['ca_certs'] = ca_file
|
||||||
|
ssl_kwargs['cert_reqs'] = ssl.CERT_REQUIRED
|
||||||
|
|
||||||
|
return ssl.wrap_socket(sock, **ssl_kwargs)
|
||||||
|
|
||||||
|
sock = None
|
||||||
|
retry_until = time.time() + 30
|
||||||
|
while not sock and time.time() < retry_until:
|
||||||
|
try:
|
||||||
|
sock = eventlet.listen(bind_addr,
|
||||||
|
backlog=backlog,
|
||||||
|
family=family)
|
||||||
|
if use_ssl:
|
||||||
|
sock = wrap_ssl(sock)
|
||||||
|
|
||||||
|
except socket.error, err:
|
||||||
|
if err.args[0] != errno.EADDRINUSE:
|
||||||
|
raise
|
||||||
|
eventlet.sleep(0.1)
|
||||||
|
if not sock:
|
||||||
|
raise RuntimeError(_("Could not bind to %(host)s:%(port)s "
|
||||||
|
"after trying for 30 seconds") %
|
||||||
|
{'host': host, 'port': port})
|
||||||
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
# sockets can hang around forever without keepalive
|
||||||
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
|
||||||
|
|
||||||
|
# This option isn't available in the OS X version of eventlet
|
||||||
|
if hasattr(socket, 'TCP_KEEPIDLE'):
|
||||||
|
sock.setsockopt(socket.IPPROTO_TCP,
|
||||||
|
socket.TCP_KEEPIDLE,
|
||||||
|
CONF.tcp_keepidle)
|
||||||
|
|
||||||
|
return sock
|
||||||
|
|
||||||
def _start(self):
|
def _start(self):
|
||||||
"""Run the blocking eventlet WSGI server.
|
"""Run the blocking eventlet WSGI server.
|
||||||
|
|
||||||
@ -92,34 +199,20 @@ class Server(object):
|
|||||||
raise exception.InvalidInput(
|
raise exception.InvalidInput(
|
||||||
reason='The backlog must be more than 1')
|
reason='The backlog must be more than 1')
|
||||||
|
|
||||||
bind_addr = (self._host, self._port)
|
self._socket = self._get_socket(self._host,
|
||||||
# TODO(dims): eventlet's green dns/socket module does not actually
|
self._port,
|
||||||
# support IPv6 in getaddrinfo(). We need to get around this in the
|
backlog=backlog)
|
||||||
# future or monitor upstream for a fix
|
|
||||||
try:
|
|
||||||
info = socket.getaddrinfo(bind_addr[0],
|
|
||||||
bind_addr[1],
|
|
||||||
socket.AF_UNSPEC,
|
|
||||||
socket.SOCK_STREAM)[0]
|
|
||||||
family = info[0]
|
|
||||||
bind_addr = info[-1]
|
|
||||||
except Exception:
|
|
||||||
family = socket.AF_INET
|
|
||||||
|
|
||||||
self._socket = eventlet.listen(bind_addr,
|
|
||||||
family,
|
|
||||||
backlog=backlog)
|
|
||||||
self._server = eventlet.spawn(self._start)
|
self._server = eventlet.spawn(self._start)
|
||||||
(self._host, self._port) = self._socket.getsockname()[0:2]
|
(self._host, self._port) = self._socket.getsockname()[0:2]
|
||||||
LOG.info(_("Started %(name)s on %(_host)s:%(_port)s") % self.__dict__)
|
LOG.info(_("Started %(name)s on %(_host)s:%(_port)s") % self.__dict__)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def host(self):
|
def host(self):
|
||||||
return self._socket.getsockname()[0] if self._socket else self._host
|
return self._host
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def port(self):
|
def port(self):
|
||||||
return self._socket.getsockname()[1] if self._socket else self._port
|
return self._port
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""Stop this server.
|
"""Stop this server.
|
||||||
|
Loading…
Reference in New Issue
Block a user