Merge "added API token based auth"

This commit is contained in:
Zuul
2025-04-24 07:57:04 +00:00
committed by Gerrit Code Review
7 changed files with 99 additions and 16 deletions
@@ -69,6 +69,7 @@ other parameters that are not specific to VAST Share Driver.
vast_mgmt_port = {vms_port}
vast_mgmt_user = {mgmt_user}
vast_mgmt_password = {mgmt_password}
vast_api_token = {vast_api_token}
vast_vippool_name = {vip_pool}
vast_root_export = {root_export}
@@ -30,3 +30,5 @@
- (String) Username for VAST management API.
* - ``vast_mgmt_password`` =
- (String) Password for VAST management API.
* - ``vast_api_token`` =
- (String) API token for accessing VAST mgmt. If provided, it will be used instead of 'vast_mgmt_user' and 'vast_mgmt_password'.
+26 -6
View File
@@ -79,6 +79,16 @@ OPTS = [
help="Password for VAST management",
secret=True
),
cfg.StrOpt(
"vast_api_token",
default="",
secret=True,
help=(
"API token for accessing VAST mgmt. "
"If provided, it will be used instead "
"of 'san_login' and 'san_password'."
)
),
]
CONF = cfg.CONF
@@ -116,19 +126,29 @@ class VASTShareDriver(driver.ShareDriver):
username = self.configuration.safe_get("vast_mgmt_user")
password = self.configuration.safe_get("vast_mgmt_password")
api_token = self.configuration.safe_get("vast_api_token")
host = self.configuration.safe_get("vast_mgmt_host")
port = self.configuration.safe_get("vast_mgmt_port")
if not all((username, password, port)):
if not host:
raise exception.VastDriverException(
reason="Not all required parameters are present."
" Make sure you specified `vast_mgmt_host`,"
" `vast_mgmt_port`, and `vast_mgmt_user` "
"in manila.conf."
reason="`vast_mgmt_host` must be set in manila.conf."
)
# Require either (username & password) OR (API token)
if not ((username and password) or api_token):
raise exception.VastDriverException(
reason="Authentication failed: You must specify either "
"`vast_mgmt_user` and `vast_mgmt_password`, "
"or provide `vast_api_token` in manila.conf."
)
if port:
host = f"{host}:{port}"
self.rest = vast_rest.RestApi(
host, username, password, False, self.VERSION
host=host,
username=username,
password=password,
api_token=api_token,
ssl_verify=False,
plugin_version=self.VERSION,
)
LOG.debug("VAST Data driver setup is complete.")
+32 -5
View File
@@ -32,20 +32,37 @@ LOG = logging.getLogger(__name__)
class Session(requests.Session):
def __init__(self, host, username, password, ssl_verify, plugin_version):
def __init__(
self,
host,
username,
password,
api_token,
ssl_verify,
plugin_version,
):
super().__init__()
self.base_url = f"https://{host.strip('/')}/api"
self.ssl_verify = ssl_verify
self.username = username
self.password = password
self.token = api_token
self.headers["Accept"] = "application/json"
self.headers["Content-Type"] = "application/json"
self.headers["User-Agent"] = (
f"manila/v{plugin_version}"
f" ({requests.utils.default_user_agent()})"
)
# will be updated on first request
self.headers["authorization"] = "Bearer"
if self.token:
LOG.info("VMS session is using API token authentication.")
self.headers["authorization"] = f"Api-Token {self.token}"
else:
# Will be updated on the first request
LOG.info(
"VMS session is using username/password authentication"
" (Bearer token will be acquired)."
)
self.headers["authorization"] = "Bearer"
if not ssl_verify:
import urllib3
@@ -95,7 +112,8 @@ class Session(requests.Session):
ret = super().request(
verb, url, verify=self.ssl_verify, params=params, **kwargs
)
if ret.status_code == 403 and "Token is invalid" in ret.text:
# No refresh for token based auth. Token should be long-lived.
if ret.status_code == 403 and not self.token:
self.refresh_auth_token()
raise exception.VastApiRetry(reason="Token is invalid or expired.")
@@ -307,11 +325,20 @@ class Folders(VastResource):
class RestApi:
def __init__(self, host, username, password, ssl_verify, plugin_version):
def __init__(
self,
host,
username,
password,
api_token,
ssl_verify,
plugin_version,
):
self.session = Session(
host=host,
username=username,
password=password,
api_token=api_token,
ssl_verify=ssl_verify,
plugin_version=plugin_version,
)
@@ -94,7 +94,7 @@ class VASTShareDriverTestCase(unittest.TestCase):
self.assertFalse(session.ssl_verify)
self.assertEqual(session.base_url, "https://test:443/api")
@ddt.data("vast_mgmt_user", "vast_vippool_name")
@ddt.data("vast_mgmt_user", "vast_vippool_name", "vast_mgmt_host")
def test_do_setup_missing_required_fields(self, missing_field):
self.fake_conf.set_default(missing_field, None)
_driver = driver.VASTShareDriver(
@@ -103,6 +103,16 @@ class VASTShareDriverTestCase(unittest.TestCase):
with self.assertRaises(exception.VastDriverException):
_driver.do_setup(self._context)
def test_do_setup_with_api_token(self):
self.fake_conf.set_default("vast_mgmt_user", None)
self.fake_conf.set_default("vast_mgmt_password", None)
self.fake_conf.set_default("vast_api_token", "test_token")
_driver = driver.VASTShareDriver(
execute=mock.MagicMock(), configuration=self.fake_conf
)
_driver.do_setup(self._context)
self.assertEqual(_driver.rest.session.token, "test_token")
@mock.patch(
"manila.share.drivers.vastdata.rest.Session.get",
mock.MagicMock(return_value=fake_metrics),
@@ -101,8 +101,12 @@ class TestSession(unittest.TestCase):
def setUp(self):
self.session = vast_rest.Session(
"host", "username",
"password", False, "1.0"
"host",
"username",
"password",
"",
False,
"1.0",
)
@mock.patch("requests.Session.request")
@@ -274,6 +278,7 @@ class ViewTest(unittest.TestCase):
"host",
"username",
"password",
"",
True,
"1.0"
)
@@ -324,6 +329,7 @@ class TestCapacityMetrics(unittest.TestCase):
"host",
"username",
"password",
"",
True,
"1.0"
)
@@ -344,7 +350,12 @@ class TestFolders(unittest.TestCase):
)
def setUp(self):
self.rest_api = vast_rest.RestApi(
"host", "username", "password", True, "1.0"
"host",
"username",
"password",
"",
True,
"1.0",
)
@ddt.data(
@@ -446,6 +457,7 @@ class VipPoolTest(unittest.TestCase):
"host",
"username",
"password",
"",
True,
"1.0"
)
@@ -506,7 +518,12 @@ class TestRestApi(unittest.TestCase):
mock.MagicMock(sys_version="1.0")
]
rest_api = vast_rest.RestApi(
"host", "username", "password", True, "1.0"
"host",
"username",
"password",
"",
True,
"1.0",
)
version = rest_api.get_sw_version()
self.assertEqual(version, "1.0")
@@ -0,0 +1,6 @@
---
features:
- Added support for authentication using an API token in the VAST Manila driver.
Introduced the `vast_api_token` configuration option, allowing users to
authenticate with a pre-generated API token instead of using `vast_mgmt_user`
and `vast_mgmt_password`.