From b3f7f12fcf11aa07cb1b4e97bc11fdb248ba2233 Mon Sep 17 00:00:00 2001 From: Peter Wang Date: Fri, 24 Mar 2017 10:10:05 +0800 Subject: [PATCH] Handle SSL from VNX driver From python 2.7.9 on, the ssl verification is enabled by default, This commit adds 2 options for VNX Manila driver, so user is able to control the ssl verification. Closes-bug: 1669202 Implements: blueprint vnx-ssl-verification-options Change-Id: Iedad15e077c0537e133f81e6d537798482789160 (cherry picked from commit bf0f42858b0f57aaf08630cda3514c822b21db09) --- manila/share/drivers/dell_emc/driver.py | 10 ++++++- .../drivers/dell_emc/plugins/vnx/connector.py | 11 +++++-- .../drivers/dell_emc/plugins/vnx/utils.py | 23 +++++++++++++++ .../dell_emc/plugins/vnx/test_connector.py | 2 ++ .../dell_emc/plugins/vnx/test_utils.py | 29 +++++++++++++++++++ ...vnx-ssl-verification-2d26a24e7e73bf81.yaml | 3 ++ 6 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 releasenotes/notes/vnx-ssl-verification-2d26a24e7e73bf81.yaml diff --git a/manila/share/drivers/dell_emc/driver.py b/manila/share/drivers/dell_emc/driver.py index f1c722944b..8643ee92e9 100644 --- a/manila/share/drivers/dell_emc/driver.py +++ b/manila/share/drivers/dell_emc/driver.py @@ -43,7 +43,15 @@ EMC_NAS_OPTS = [ choices=['isilon', 'vnx', 'unity', 'vmax'], help='Share backend.'), cfg.StrOpt('emc_nas_root_dir', - help='The root directory where shares will be located.') + help='The root directory where shares will be located.'), + cfg.BoolOpt('emc_ssl_cert_verify', + default=True, + help='If set to False the https client will not validate the ' + 'SSL certificate of the backend endpoint.'), + cfg.StrOpt('emc_ssl_cert_path', + help='Can be used to specify a non default path to a ' + 'CA_BUNDLE file or directory with certificates of trusted ' + 'CAs, which will be used to validate the backend.') ] CONF = cfg.CONF diff --git a/manila/share/drivers/dell_emc/plugins/vnx/connector.py b/manila/share/drivers/dell_emc/plugins/vnx/connector.py index ce6d3c8149..783dba4f5b 100644 --- a/manila/share/drivers/dell_emc/plugins/vnx/connector.py +++ b/manila/share/drivers/dell_emc/plugins/vnx/connector.py @@ -27,6 +27,7 @@ from manila import exception from manila.i18n import _ from manila.i18n import _LE from manila.share.drivers.dell_emc.plugins.vnx import constants +from manila.share.drivers.dell_emc.plugins.vnx import utils as vnx_utils from manila import utils LOG = log.getLogger(__name__) @@ -40,9 +41,13 @@ class XMLAPIConnector(object): self.password = configuration.emc_nas_password self.debug = debug self.auth_url = 'https://' + self.storage_ip + '/Login' - self._url = ('https://' + self.storage_ip - + '/servlets/CelerraManagementServices') - https_handler = url_request.HTTPSHandler() + self._url = 'https://{}/servlets/CelerraManagementServices'.format( + self.storage_ip) + context = vnx_utils.create_ssl_context(configuration) + if context: + https_handler = url_request.HTTPSHandler(context=context) + else: + https_handler = url_request.HTTPSHandler() cookie_handler = url_request.HTTPCookieProcessor( http_cookiejar.CookieJar()) self.url_opener = url_request.build_opener(https_handler, diff --git a/manila/share/drivers/dell_emc/plugins/vnx/utils.py b/manila/share/drivers/dell_emc/plugins/vnx/utils.py index 66c9822273..dfc07f6c7a 100644 --- a/manila/share/drivers/dell_emc/plugins/vnx/utils.py +++ b/manila/share/drivers/dell_emc/plugins/vnx/utils.py @@ -15,10 +15,12 @@ import types +from manila.i18n import _LW from oslo_config import cfg from oslo_log import log from oslo_utils import fnmatch from oslo_utils import timeutils +import ssl CONF = cfg.CONF LOG = log.getLogger(__name__) @@ -81,3 +83,24 @@ def do_match_any(full, matcher_list): matched.add(item) not_matched = full - matched return matched, not_matched + + +def create_ssl_context(configuration): + """Create context for ssl verification. + + .. note:: starting from python 2.7.9 ssl adds create_default_context. + We need to keep compatibility with previous python as well. + """ + try: + if configuration.emc_ssl_cert_verify: + context = ssl.create_default_context( + capath=configuration.emc_ssl_cert_path) + else: + context = ssl.create_default_context() + context.check_hostname = False + context.verify_mode = ssl.CERT_NONE + except AttributeError: + LOG.warning(_LW('Creating ssl context is not supported on this ' + 'version of Python, ssl verification is disabled.')) + context = None + return context diff --git a/manila/tests/share/drivers/dell_emc/plugins/vnx/test_connector.py b/manila/tests/share/drivers/dell_emc/plugins/vnx/test_connector.py index 6cea7e7253..54263c8481 100644 --- a/manila/tests/share/drivers/dell_emc/plugins/vnx/test_connector.py +++ b/manila/tests/share/drivers/dell_emc/plugins/vnx/test_connector.py @@ -160,6 +160,8 @@ class CmdConnectorTest(test.TestCase): self.configuration.emc_nas_login = fakes.FakeData.emc_nas_login self.configuration.emc_nas_password = fakes.FakeData.emc_nas_password self.configuration.emc_nas_server = fakes.FakeData.emc_nas_server + self.configuration.emc_ssl_cert_verify = False + self.configuration.emc_ssl_cert_path = None self.sshpool = MockSSHPool() with mock.patch.object(utils, "SSHPool", diff --git a/manila/tests/share/drivers/dell_emc/plugins/vnx/test_utils.py b/manila/tests/share/drivers/dell_emc/plugins/vnx/test_utils.py index 5771f0275c..22131dd916 100644 --- a/manila/tests/share/drivers/dell_emc/plugins/vnx/test_utils.py +++ b/manila/tests/share/drivers/dell_emc/plugins/vnx/test_utils.py @@ -14,6 +14,8 @@ # under the License. import ddt +import mock +import ssl from manila.share.drivers.dell_emc.plugins.vnx import utils from manila import test @@ -42,3 +44,30 @@ class VNXUtilsTestCase(test.TestCase): full, matchers) self.assertEqual(matched, real_matched) self.assertEqual(unmatched, real_unmatched) + + +class SslContextTestCase(test.TestCase): + + def test_create_ssl_context(self): + configuration = mock.Mock() + configuration.emc_ssl_cert_verify = True + configuration.emc_ssl_cert_path = "./cert_path/" + self.mock_object(ssl, 'create_default_context') + context = utils.create_ssl_context(configuration) + self.assertIsNotNone(context) + + def test_create_ssl_context_no_verify(self): + configuration = mock.Mock() + configuration.emc_ssl_cert_verify = False + self.mock_object(ssl, 'create_default_context') + context = utils.create_ssl_context(configuration) + self.assertFalse(context.check_hostname) + + def test_no_create_default_context(self): + """Test scenario of running on python 2.7.8 or earlier.""" + configuration = mock.Mock() + configuration.emc_ssl_cert_verify = False + self.mock_object(ssl, 'create_default_context', + mock.Mock(side_effect=AttributeError)) + context = utils.create_ssl_context(configuration) + self.assertIsNone(context) diff --git a/releasenotes/notes/vnx-ssl-verification-2d26a24e7e73bf81.yaml b/releasenotes/notes/vnx-ssl-verification-2d26a24e7e73bf81.yaml new file mode 100644 index 0000000000..d5fb9d685d --- /dev/null +++ b/releasenotes/notes/vnx-ssl-verification-2d26a24e7e73bf81.yaml @@ -0,0 +1,3 @@ +upgrade: + - Added ``emc_ssl_cert_verify`` and ``emc_ssl_cert_path`` options for VNX SSL + verification. For more details, see OpenStack official documentation.