From 72c63681178286ed9cd1e1ab48969a64b9004d7c Mon Sep 17 00:00:00 2001 From: Ivan Pchelintsev Date: Tue, 2 Jun 2020 16:23:04 +0300 Subject: [PATCH] Remove VxFlex OS credentials from connection_properties VxFlex OS password is not stored in block_device_mapping table. Instead of this passwords are stored in separate file and are retrieved during each attach/detach operation. Closes-Bug: #1823200 Change-Id: Ib7778ba9d38a68d8b56ca632c5f1c353d55830b0 --- os_brick/initiator/connectors/scaleio.py | 35 +++++++++++++++++-- .../initiator/connectors/test_scaleio.py | 8 +++-- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/os_brick/initiator/connectors/scaleio.py b/os_brick/initiator/connectors/scaleio.py index e07911bdd..d134e0eff 100644 --- a/os_brick/initiator/connectors/scaleio.py +++ b/os_brick/initiator/connectors/scaleio.py @@ -15,6 +15,8 @@ import json import os import requests +import six +from six.moves import configparser from six.moves import urllib from oslo_concurrency import lockutils @@ -29,6 +31,7 @@ from os_brick import utils LOG = logging.getLogger(__name__) DEVICE_SCAN_ATTEMPTS_DEFAULT = 3 +CONNECTOR_CONF_PATH = '/opt/emc/scaleio/openstack/connector.conf' synchronized = lockutils.synchronized_with_prefix('os-brick-') @@ -39,6 +42,7 @@ class ScaleIOConnector(base.BaseLinuxConnector): VOLUME_NOT_MAPPED_ERROR = 84 VOLUME_ALREADY_MAPPED_ERROR = 81 GET_GUID_CMD = ['/opt/emc/scaleio/sdc/bin/drv_cfg', '--query_guid'] + GET_PASSWORD_CMD = ['cat', CONNECTOR_CONF_PATH] def __init__(self, root_helper, driver=None, device_scan_attempts=initiator.DEVICE_SCAN_ATTEMPTS_DEFAULT, @@ -221,6 +225,32 @@ class ScaleIOConnector(base.BaseLinuxConnector): {'volume_id': volume_id}) return volume_id + def _get_connector_password(self, config_group): + LOG.info("Get ScaleIO connector password from configuration file") + + if not os.path.isfile(CONNECTOR_CONF_PATH): + msg = ("ScaleIO connector configuration file " + "is not found in path %s." % CONNECTOR_CONF_PATH) + raise exception.BrickException(message=msg) + + try: + (out, err) = self._execute(*self.GET_PASSWORD_CMD, + run_as_root=True, + root_helper=self._root_helper) + conf = configparser.ConfigParser() + conf.readfp(six.StringIO(out)) + return conf[config_group]["san_password"] + except putils.ProcessExecutionError as e: + msg = _("Error reading ScaleIO connector " + "configuration file: %s") % e.stderr + LOG.error(msg) + raise exception.BrickException(message=msg) + except Exception as e: + msg = _("Error getting ScaleIO connector password from " + "configuration file: %s") % e + LOG.error(msg) + raise exception.BrickException(message=msg) + def _check_response(self, response, request, is_get_request=True, params=None): if response.status_code == 401 or response.status_code == 403: @@ -269,8 +299,9 @@ class ScaleIOConnector(base.BaseLinuxConnector): self.server_ip = connection_properties['serverIP'] self.server_port = connection_properties['serverPort'] self.server_username = connection_properties['serverUsername'] - self.server_password = connection_properties['serverPassword'] - self.server_token = connection_properties['serverToken'] + self.server_password = self._get_connector_password( + connection_properties['config_group'], + ) self.iops_limit = connection_properties['iopsLimit'] self.bandwidth_limit = connection_properties['bandwidthLimit'] device_info = {'type': 'block', diff --git a/os_brick/tests/initiator/connectors/test_scaleio.py b/os_brick/tests/initiator/connectors/test_scaleio.py index 146ed43f8..45f807b8d 100644 --- a/os_brick/tests/initiator/connectors/test_scaleio.py +++ b/os_brick/tests/initiator/connectors/test_scaleio.py @@ -47,8 +47,7 @@ class ScaleIOConnectorTestCase(test_connector.ConnectorTestCase): 'scaleIO_volume_id': self.vol['provider_id'], 'serverPort': 443, 'serverUsername': 'test', - 'serverPassword': 'fake', - 'serverToken': 'fake_token', + 'config_group': 'test', 'iopsLimit': None, 'bandwidthLimit': None } @@ -84,6 +83,10 @@ class ScaleIOConnectorTestCase(test_connector.ConnectorTestCase): self.mock_object(os, 'listdir', return_value=["emc-vol-{}".format(self.vol['id'])]) + self.get_password_mock = self.mock_object(scaleio.ScaleIOConnector, + '_get_connector_password', + return_value='fake_password') + # The actual ScaleIO connector self.connector = scaleio.ScaleIOConnector( 'sudo', execute=self.fake_execute) @@ -170,6 +173,7 @@ class ScaleIOConnectorTestCase(test_connector.ConnectorTestCase): def test_connect_volume(self): """Successful connect to volume""" self.connector.connect_volume(self.fake_connection_properties) + self.get_password_mock.assert_called_once() def test_connect_with_bandwidth_limit(self): """Successful connect to volume with bandwidth limit"""