summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavanum Srinivas <dims@linux.vnet.ibm.com>2013-07-02 09:08:29 -0400
committerDavanum Srinivas <dims@linux.vnet.ibm.com>2013-07-08 08:58:58 -0400
commit99b7c354271e2ed0893b3c48c7f2a58a55b59b11 (patch)
tree303737580276d57f3a81963bef440ff77f8f987b
parentabfd8ca6ca13b8ad1d42f081aaf29ec639a4032c (diff)
downloadoslo-99b7c354271e2ed0893b3c48c7f2a58a55b59b11.tar.gz
oslo-99b7c354271e2ed0893b3c48c7f2a58a55b59b11.tar.xz
oslo-99b7c354271e2ed0893b3c48c7f2a58a55b59b11.zip
Convert kombu SSL version string into integer
When specifying 'kombu_ssl_version' for the RPC driver such as either "kombu_ssl_version=3" or "kombu_ssl_version=SSLv3" the relevant OpenStack service (nova, cinder, etc) will fail as the underlying rpc driver is trying to create an SSL socket which requires an integer such as the following built-in SSL integer constants. Added a validation step that ensures one can set only the supported ssl versions and to convert from the specified string to an integer Fixes LP# 1195431 Change-Id: I5d188f46a15bc4ba60d573d6b98def60c56cb987
-rw-r--r--openstack/common/rpc/impl_kombu.py9
-rw-r--r--openstack/common/sslutils.py20
-rw-r--r--tests/unit/rpc/test_kombu_ssl.py25
-rw-r--r--tests/unit/test_sslutils.py66
4 files changed, 116 insertions, 4 deletions
diff --git a/openstack/common/rpc/impl_kombu.py b/openstack/common/rpc/impl_kombu.py
index 36d2fc5..70f19b4 100644
--- a/openstack/common/rpc/impl_kombu.py
+++ b/openstack/common/rpc/impl_kombu.py
@@ -34,11 +34,15 @@ from openstack.common.gettextutils import _
from openstack.common import network_utils
from openstack.common.rpc import amqp as rpc_amqp
from openstack.common.rpc import common as rpc_common
+from openstack.common import sslutils
kombu_opts = [
cfg.StrOpt('kombu_ssl_version',
default='',
- help='SSL version to use (valid only if SSL enabled)'),
+ help='SSL version to use (valid only if SSL enabled). '
+ 'valid values are TLSv1, SSLv23 and SSLv3. SSLv2 may '
+ 'be available on some distributions'
+ ),
cfg.StrOpt('kombu_ssl_keyfile',
default='',
help='SSL key file (valid only if SSL enabled)'),
@@ -477,7 +481,8 @@ class Connection(object):
# http://docs.python.org/library/ssl.html - ssl.wrap_socket
if self.conf.kombu_ssl_version:
- ssl_params['ssl_version'] = self.conf.kombu_ssl_version
+ ssl_params['ssl_version'] = sslutils.validate_ssl_version(
+ self.conf.kombu_ssl_version)
if self.conf.kombu_ssl_keyfile:
ssl_params['keyfile'] = self.conf.kombu_ssl_keyfile
if self.conf.kombu_ssl_certfile:
diff --git a/openstack/common/sslutils.py b/openstack/common/sslutils.py
index 252da72..281684b 100644
--- a/openstack/common/sslutils.py
+++ b/openstack/common/sslutils.py
@@ -78,3 +78,23 @@ def wrap(sock):
ssl_kwargs['cert_reqs'] = ssl.CERT_REQUIRED
return ssl.wrap_socket(sock, **ssl_kwargs)
+
+
+_SSL_PROTOCOLS = {
+ "tlsv1": ssl.PROTOCOL_TLSv1,
+ "sslv23": ssl.PROTOCOL_SSLv23,
+ "sslv3": ssl.PROTOCOL_SSLv3
+}
+
+try:
+ _SSL_PROTOCOLS["sslv2"] = ssl.PROTOCOL_SSLv2
+except AttributeError:
+ pass
+
+
+def validate_ssl_version(version):
+ key = version.lower()
+ try:
+ return _SSL_PROTOCOLS[key]
+ except KeyError:
+ raise RuntimeError(_("Invalid SSL version : %s") % version)
diff --git a/tests/unit/rpc/test_kombu_ssl.py b/tests/unit/rpc/test_kombu_ssl.py
index 688c992..2a0b170 100644
--- a/tests/unit/rpc/test_kombu_ssl.py
+++ b/tests/unit/rpc/test_kombu_ssl.py
@@ -20,6 +20,7 @@ Unit Tests for remote procedure calls using kombu + ssl
"""
import eventlet
+import ssl
eventlet.monkey_patch()
from oslo.config import cfg
@@ -36,7 +37,7 @@ except ImportError:
# Flag settings we will ensure get passed to amqplib
-SSL_VERSION = "SSLv2"
+SSL_VERSION = "SSLv3"
SSL_CERT = "/tmp/cert.blah.blah"
SSL_CA_CERT = "/tmp/cert.ca.blah.blah"
SSL_KEYFILE = "/tmp/keyfile.blah.blah"
@@ -64,9 +65,29 @@ class RpcKombuSslTestCase(test_utils.BaseTestCase):
#This might be kombu version dependent...
#Since we are now peaking into the internals of kombu...
self.assertTrue(isinstance(c.connection.ssl, dict))
- self.assertEqual(SSL_VERSION, c.connection.ssl.get("ssl_version"))
+ self.assertEqual(ssl.PROTOCOL_SSLv3,
+ c.connection.ssl.get("ssl_version"))
self.assertEqual(SSL_CERT, c.connection.ssl.get("certfile"))
self.assertEqual(SSL_CA_CERT, c.connection.ssl.get("ca_certs"))
self.assertEqual(SSL_KEYFILE, c.connection.ssl.get("keyfile"))
#That hash then goes into amqplib which then goes
#Into python ssl creation...
+
+
+class RpcKombuSslBadVersionTestCase(test_utils.BaseTestCase):
+
+ def setUp(self):
+ super(RpcKombuSslBadVersionTestCase, self).setUp()
+ if kombu is None:
+ self.skipTest("Test requires kombu")
+ self.config(kombu_ssl_keyfile=SSL_KEYFILE,
+ kombu_ssl_ca_certs=SSL_CA_CERT,
+ kombu_ssl_certfile=SSL_CERT,
+ kombu_ssl_version="SSLv24",
+ rabbit_use_ssl=True,
+ fake_rabbit=True)
+
+ def test_bad_ssl_version(self):
+ rpc = impl_kombu
+ self.assertRaises(RuntimeError,
+ rpc.create_connection, FLAGS, True)
diff --git a/tests/unit/test_sslutils.py b/tests/unit/test_sslutils.py
new file mode 100644
index 0000000..4c0646e
--- /dev/null
+++ b/tests/unit/test_sslutils.py
@@ -0,0 +1,66 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM Corp.
+#
+# 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.
+
+import ssl
+
+from openstack.common import sslutils
+from tests import utils
+
+
+class SSLUtilsTest(utils.BaseTestCase):
+ def test_valid_versions(self):
+ self.assertEquals(sslutils.validate_ssl_version("SSLv3"),
+ ssl.PROTOCOL_SSLv3)
+ self.assertEquals(sslutils.validate_ssl_version("SSLv23"),
+ ssl.PROTOCOL_SSLv23)
+ self.assertEquals(sslutils.validate_ssl_version("TLSv1"),
+ ssl.PROTOCOL_TLSv1)
+ try:
+ protocol = ssl.PROTOCOL_SSLv2
+ except AttributeError:
+ pass
+ else:
+ self.assertEquals(sslutils.validate_ssl_version("SSLv2"),
+ protocol)
+
+ def test_lowercase_valid_versions(self):
+ self.assertEquals(sslutils.validate_ssl_version("sslv3"),
+ ssl.PROTOCOL_SSLv3)
+ self.assertEquals(sslutils.validate_ssl_version("sslv23"),
+ ssl.PROTOCOL_SSLv23)
+ self.assertEquals(sslutils.validate_ssl_version("tlsv1"),
+ ssl.PROTOCOL_TLSv1)
+ try:
+ protocol = ssl.PROTOCOL_SSLv2
+ except AttributeError:
+ pass
+ else:
+ self.assertEquals(sslutils.validate_ssl_version("sslv2"),
+ protocol)
+
+ def test_invalid_version(self):
+ self.assertRaises(RuntimeError,
+ sslutils.validate_ssl_version,
+ "v3")
+
+ # Some distributions do not have SSLv2 enabled, make sure
+ # we throw a runtime error
+ try:
+ ssl.PROTOCOL_SSLv2
+ except AttributeError:
+ self.assertRaises(RuntimeError,
+ sslutils.validate_ssl_version,
+ "SSLv2")