]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Allow for Pure drivers to verify HTTPS requests
authorPatrick East <patrick.east@purestorage.com>
Wed, 17 Feb 2016 04:38:22 +0000 (20:38 -0800)
committerPatrick East <patrick.east@purestorage.com>
Thu, 3 Mar 2016 01:19:29 +0000 (01:19 +0000)
This pipes in the config options (driver_ssl_cert_verify and
driver_ssl_cert_path) for verifying https requests to the
purestorage python module. This will allow for the underlying https
management API requests to the array to be verified.

To use this feature a newer (>1.4.0) version of the pure storage python
module will be required.

DocImpact: Need to update Pure Storage Volume Driver config reference
to mention that it can use the new config options and the python module
version requirements that go along with it.

Change-Id: Id4d73e76ec64e4ac00291ed9b7377c47e40bc551
Closes-Bug: #1546655

cinder/tests/unit/test_pure.py
cinder/volume/drivers/pure.py
releasenotes/notes/pure-verify-https-requests-464320c97ba77a1f.yaml [new file with mode: 0644]

index 46ca32bb673eb937b4ede7aa7f9f324c41a2d669..d80a81608f6ca4c75a3a269f9d91ec12d56cbf2a 100644 (file)
@@ -343,6 +343,8 @@ class PureDriverTestCase(test.TestCase):
         self.mock_config.volume_backend_name = VOLUME_BACKEND_NAME
         self.mock_config.safe_get.return_value = None
         self.mock_config.pure_eradicate_on_delete = False
+        self.mock_config.driver_ssl_cert_verify = False
+        self.mock_config.driver_ssl_cert_path = None
         self.array = mock.Mock()
         self.array.get.return_value = GET_ARRAY_PRIMARY
         self.array.array_name = GET_ARRAY_PRIMARY["array_name"]
@@ -352,6 +354,7 @@ class PureDriverTestCase(test.TestCase):
         self.array2.array_id = GET_ARRAY_SECONDARY["id"]
         self.array2.get.return_value = GET_ARRAY_SECONDARY
         self.purestorage_module = pure.purestorage
+        self.purestorage_module.VERSION = '1.4.0'
         self.purestorage_module.PureHTTPError = FakePureStorageHTTPError
 
     def fake_get_array(*args, **kwargs):
@@ -392,6 +395,7 @@ class PureBaseSharedDriverTestCase(PureDriverTestCase):
         super(PureBaseSharedDriverTestCase, self).tearDown()
 
 
+@ddt.ddt
 class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
     def setUp(self):
         super(PureBaseVolumeDriverTestCase, self).setUp()
@@ -1885,6 +1889,58 @@ class PureBaseVolumeDriverTestCase(PureBaseSharedDriverTestCase):
             remvollist=[VOLUME_PURITY_NAME]
         )
 
+    @ddt.data(dict(version='1.5.0'), dict(version='2.0.0'))
+    @ddt.unpack
+    def test_get_flasharray_verify_https(self, version):
+        self.purestorage_module.VERSION = version
+        san_ip = '1.2.3.4'
+        api_token = 'abcdef'
+        cert_path = '/my/ssl/certs'
+        self.purestorage_module.FlashArray.return_value = mock.MagicMock()
+
+        self.driver._get_flasharray(san_ip,
+                                    api_token,
+                                    verify_https=True,
+                                    ssl_cert_path=cert_path)
+        self.purestorage_module.FlashArray.assert_called_with(
+            san_ip,
+            api_token=api_token,
+            rest_version=None,
+            verify_https=True,
+            ssl_cert=cert_path
+        )
+
+    def test_get_flasharray_dont_verify_https_version_too_old(self):
+        self.purestorage_module.VERSION = '1.4.0'
+        san_ip = '1.2.3.4'
+        api_token = 'abcdef'
+        self.purestorage_module.FlashArray.return_value = mock.MagicMock()
+
+        self.driver._get_flasharray(san_ip,
+                                    api_token,
+                                    verify_https=False,
+                                    ssl_cert_path=None)
+        self.purestorage_module.FlashArray.assert_called_with(
+            san_ip,
+            api_token=api_token,
+            rest_version=None
+        )
+
+    def test_get_flasharray_verify_https_version_too_old(self):
+        self.purestorage_module.VERSION = '1.4.0'
+        san_ip = '1.2.3.4'
+        api_token = 'abcdef'
+        self.purestorage_module.FlashArray.return_value = mock.MagicMock()
+
+        self.assertRaises(
+            exception.PureDriverException,
+            self.driver._get_flasharray,
+            san_ip,
+            api_token,
+            verify_https=True,
+            ssl_cert_path='/my/ssl/certs'
+        )
+
 
 class PureISCSIDriverTestCase(PureDriverTestCase):
 
index b2f0fc06a3ab7e42e663a6d8c3bc7f724f083892..1b48157b60f973621a7446d026fe8031968266dc 100644 (file)
@@ -168,7 +168,14 @@ class PureBaseVolumeDriver(san.SanDriver):
                 backend_id = replication_device["backend_id"]
                 san_ip = replication_device["san_ip"]
                 api_token = replication_device["api_token"]
-                target_array = self._get_flasharray(san_ip, api_token)
+                verify_https = replication_device.get("ssl_cert_verify", False)
+                ssl_cert_path = replication_device.get("ssl_cert_path", None)
+                target_array = self._get_flasharray(
+                    san_ip,
+                    api_token,
+                    verify_https=verify_https,
+                    ssl_cert_path=ssl_cert_path
+                )
                 target_array._backend_id = backend_id
                 LOG.debug("Adding san_ip %(san_ip)s to replication_targets.",
                           {"san_ip": san_ip})
@@ -210,8 +217,10 @@ class PureBaseVolumeDriver(san.SanDriver):
             self.SUPPORTED_REST_API_VERSIONS
         self._array = self._get_flasharray(
             self.configuration.san_ip,
-            api_token=self.configuration.pure_api_token)
-
+            api_token=self.configuration.pure_api_token,
+            verify_https=self.configuration.driver_ssl_cert_verify,
+            ssl_cert_path=self.configuration.driver_ssl_cert_path
+        )
         self._array._backend_id = self._backend_name
         LOG.debug("Primary array backend_id: %s",
                   self.configuration.config_group)
@@ -942,10 +951,31 @@ class PureBaseVolumeDriver(san.SanDriver):
         self._rename_volume_object(snap_name, unmanaged_snap_name)
 
     @staticmethod
-    def _get_flasharray(san_ip, api_token, rest_version=None):
-        array = purestorage.FlashArray(san_ip,
-                                       api_token=api_token,
-                                       rest_version=rest_version)
+    def _get_flasharray(san_ip, api_token, rest_version=None,
+                        verify_https=None, ssl_cert_path=None):
+        # Older versions of the module (1.4.0) do not support setting ssl certs
+        # TODO(patrickeast): In future releases drop support for 1.4.0
+        module_version = purestorage.VERSION.split('.')
+        major_version = int(module_version[0])
+        minor_version = int(module_version[1])
+        if major_version > 1 or (major_version == 1 and minor_version > 4):
+            array = purestorage.FlashArray(san_ip,
+                                           api_token=api_token,
+                                           rest_version=rest_version,
+                                           verify_https=verify_https,
+                                           ssl_cert=ssl_cert_path)
+        else:
+            if verify_https or ssl_cert_path is not None:
+                msg = _('HTTPS certificate verification was requested '
+                        'but cannot be enabled with purestorage '
+                        'module version %(version)s. Upgrade to a '
+                        'newer version to enable this feature.') % {
+                    'version': purestorage.VERSION
+                }
+                raise exception.PureDriverException(reason=msg)
+            array = purestorage.FlashArray(san_ip,
+                                           api_token=api_token,
+                                           rest_version=rest_version)
         array_info = array.get()
         array.array_name = array_info["array_name"]
         array.array_id = array_info["id"]
@@ -1135,7 +1165,9 @@ class PureBaseVolumeDriver(san.SanDriver):
             target_array = self._get_flasharray(
                 secondary_array._target,
                 api_token=secondary_array._api_token,
-                rest_version='1.3'
+                rest_version='1.3',
+                verify_https=secondary_array._verify_https,
+                ssl_cert_path=secondary_array._ssl_cert
             )
         else:
             target_array = secondary_array
diff --git a/releasenotes/notes/pure-verify-https-requests-464320c97ba77a1f.yaml b/releasenotes/notes/pure-verify-https-requests-464320c97ba77a1f.yaml
new file mode 100644 (file)
index 0000000..3c227aa
--- /dev/null
@@ -0,0 +1,5 @@
+---
+security:
+  - Pure Storage Volume Drivers can now utilize driver_ssl_cert_verify and
+    driver_ssl_cert_path config options to allow for secure https requests to
+    the FlashArray.