Merge "Support passing client certificates for server version requests"

This commit is contained in:
Zuul 2021-04-20 21:50:38 +00:00 committed by Gerrit Code Review
commit c559f090ff
6 changed files with 56 additions and 15 deletions

View File

@ -70,7 +70,7 @@ for svc in ('volume', 'volumev2', 'volumev3'):
discover.add_catalog_discover_hack(svc, re.compile(r'/v[12]/\w+/?$'), '/') discover.add_catalog_discover_hack(svc, re.compile(r'/v[12]/\w+/?$'), '/')
def get_server_version(url, insecure=False, cacert=None): def get_server_version(url, insecure=False, cacert=None, cert=None):
"""Queries the server via the naked endpoint and gets version info. """Queries the server via the naked endpoint and gets version info.
:param url: url of the cinder endpoint :param url: url of the cinder endpoint
@ -78,6 +78,10 @@ def get_server_version(url, insecure=False, cacert=None):
(https) requests (https) requests
:param cacert: Specify a CA bundle file to use in verifying a TLS :param cacert: Specify a CA bundle file to use in verifying a TLS
(https) server certificate (https) server certificate
:param cert: A client certificate to pass to requests. These are of the
same form as requests expects. Either a single filename
containing both the certificate and key or a tuple containing
the path to the certificate then a path to the key. (optional)
:returns: APIVersion object for min and max version supported by :returns: APIVersion object for min and max version supported by
the server the server
""" """
@ -115,7 +119,7 @@ def get_server_version(url, insecure=False, cacert=None):
verify_cert = cacert verify_cert = cacert
else: else:
verify_cert = True verify_cert = True
response = requests.get(version_url, verify=verify_cert) response = requests.get(version_url, verify=verify_cert, cert=cert)
data = json.loads(response.text) data = json.loads(response.text)
versions = data['versions'] versions = data['versions']
for version in versions: for version in versions:
@ -135,9 +139,10 @@ def get_server_version(url, insecure=False, cacert=None):
api_versions.APIVersion(current_version)) api_versions.APIVersion(current_version))
def get_highest_client_server_version(url, insecure=False, cacert=None): def get_highest_client_server_version(url, insecure=False,
cacert=None, cert=None):
"""Returns highest supported version by client and server as a string.""" """Returns highest supported version by client and server as a string."""
min_server, max_server = get_server_version(url, insecure, cacert) min_server, max_server = get_server_version(url, insecure, cacert, cert)
max_client = api_versions.APIVersion(api_versions.MAX_VERSION) max_client = api_versions.APIVersion(api_versions.MAX_VERSION)
return min(max_server, max_client).get_string() return min(max_server, max_client).get_string()
@ -286,7 +291,7 @@ class HTTPClient(object):
endpoint_type='publicURL', service_type=None, endpoint_type='publicURL', service_type=None,
service_name=None, volume_service_name=None, service_name=None, volume_service_name=None,
os_endpoint=None, retries=None, os_endpoint=None, retries=None,
http_log_debug=False, cacert=None, http_log_debug=False, cacert=None, cert=None,
auth_system='keystone', auth_plugin=None, api_version=None, auth_system='keystone', auth_plugin=None, api_version=None,
logger=None, user_domain_name='Default', logger=None, user_domain_name='Default',
project_domain_name='Default', global_request_id=None): project_domain_name='Default', global_request_id=None):
@ -324,7 +329,7 @@ class HTTPClient(object):
self.timeout = timeout self.timeout = timeout
self.user_domain_name = user_domain_name self.user_domain_name = user_domain_name
self.project_domain_name = project_domain_name self.project_domain_name = project_domain_name
self.cert = cert
if insecure: if insecure:
self.verify_cert = False self.verify_cert = False
else: else:
@ -405,6 +410,7 @@ class HTTPClient(object):
method, method,
url, url,
verify=self.verify_cert, verify=self.verify_cert,
cert=self.cert,
**kwargs) **kwargs)
self.http_log_resp(resp) self.http_log_resp(resp)
@ -701,7 +707,7 @@ def _construct_http_client(username=None, password=None, project_id=None,
os_endpoint=None, retries=None, os_endpoint=None, retries=None,
http_log_debug=False, http_log_debug=False,
auth_system='keystone', auth_plugin=None, auth_system='keystone', auth_plugin=None,
cacert=None, tenant_id=None, cacert=None, cert=None, tenant_id=None,
session=None, session=None,
auth=None, api_version=None, auth=None, api_version=None,
**kwargs): **kwargs):
@ -741,6 +747,7 @@ def _construct_http_client(username=None, password=None, project_id=None,
retries=retries, retries=retries,
http_log_debug=http_log_debug, http_log_debug=http_log_debug,
cacert=cacert, cacert=cacert,
cert=cert,
auth_system=auth_system, auth_system=auth_system,
auth_plugin=auth_plugin, auth_plugin=auth_plugin,
logger=logger, logger=logger,

View File

@ -365,7 +365,9 @@ class GetAPIVersionTestCase(utils.TestCase):
cinderclient.client.get_server_version(url, True) cinderclient.client.get_server_version(url, True)
mock_request.assert_called_once_with(expected_url, verify=False) mock_request.assert_called_once_with(expected_url,
verify=False,
cert=None)
@mock.patch('cinderclient.client.requests.get') @mock.patch('cinderclient.client.requests.get')
def test_get_server_version_cacert(self, mock_request): def test_get_server_version_cacert(self, mock_request):
@ -383,7 +385,29 @@ class GetAPIVersionTestCase(utils.TestCase):
cacert = '/path/to/cert' cacert = '/path/to/cert'
cinderclient.client.get_server_version(url, cacert=cacert) cinderclient.client.get_server_version(url, cacert=cacert)
mock_request.assert_called_once_with(expected_url, verify=cacert) mock_request.assert_called_once_with(expected_url,
verify=cacert,
cert=None)
@mock.patch('cinderclient.client.requests.get')
def test_get_server_version_cert(self, mock_request):
mock_response = utils.TestResponse({
"status_code": 200,
"text": json.dumps(fakes.fake_request_get_no_v3())
})
mock_request.return_value = mock_response
url = (
"https://192.168.122.127:8776/v3/e5526285ebd741b1819393f772f11fc3")
expected_url = "https://192.168.122.127:8776/"
client_cert = '/path/to/cert'
cinderclient.client.get_server_version(url, cert=client_cert)
mock_request.assert_called_once_with(expected_url,
verify=True,
cert=client_cert)
@mock.patch('cinderclient.client.requests.get') @mock.patch('cinderclient.client.requests.get')
@ddt.data('3.12', '3.40') @ddt.data('3.12', '3.40')

View File

@ -27,6 +27,7 @@ REQUEST_ID = ['req-test-request-id']
class TestCase(testtools.TestCase): class TestCase(testtools.TestCase):
TEST_REQUEST_BASE = { TEST_REQUEST_BASE = {
'verify': True, 'verify': True,
'cert': None
} }
def setUp(self): def setUp(self):

View File

@ -56,9 +56,9 @@ class Client(object):
endpoint_type='publicURL', extensions=None, endpoint_type='publicURL', extensions=None,
service_type='volumev2', service_name=None, service_type='volumev2', service_name=None,
volume_service_name=None, os_endpoint=None, retries=0, volume_service_name=None, os_endpoint=None, retries=0,
http_log_debug=False, cacert=None, auth_system='keystone', http_log_debug=False, cacert=None, cert=None,
auth_plugin=None, session=None, api_version=None, auth_system='keystone', auth_plugin=None, session=None,
logger=None, **kwargs): api_version=None, logger=None, **kwargs):
# FIXME(comstud): Rename the api_key argument above when we # FIXME(comstud): Rename the api_key argument above when we
# know it's not being used as keyword argument # know it's not being used as keyword argument
password = api_key password = api_key
@ -118,6 +118,7 @@ class Client(object):
retries=retries, retries=retries,
http_log_debug=http_log_debug, http_log_debug=http_log_debug,
cacert=cacert, cacert=cacert,
cert=cert,
auth_system=auth_system, auth_system=auth_system,
auth_plugin=auth_plugin, auth_plugin=auth_plugin,
session=session, session=session,

View File

@ -63,9 +63,9 @@ class Client(object):
endpoint_type='publicURL', extensions=None, endpoint_type='publicURL', extensions=None,
service_type='volumev3', service_name=None, service_type='volumev3', service_name=None,
volume_service_name=None, os_endpoint=None, retries=0, volume_service_name=None, os_endpoint=None, retries=0,
http_log_debug=False, cacert=None, auth_system='keystone', http_log_debug=False, cacert=None, cert=None,
auth_plugin=None, session=None, api_version=None, auth_system='keystone', auth_plugin=None, session=None,
logger=None, **kwargs): api_version=None, logger=None, **kwargs):
# FIXME(comstud): Rename the api_key argument above when we # FIXME(comstud): Rename the api_key argument above when we
# know it's not being used as keyword argument # know it's not being used as keyword argument
password = api_key password = api_key
@ -131,6 +131,7 @@ class Client(object):
retries=retries, retries=retries,
http_log_debug=http_log_debug, http_log_debug=http_log_debug,
cacert=cacert, cacert=cacert,
cert=cert,
auth_system=auth_system, auth_system=auth_system,
auth_plugin=auth_plugin, auth_plugin=auth_plugin,
session=session, session=session,

View File

@ -0,0 +1,7 @@
---
fixes:
- |
`Bug #1915996 <https://bugs.launchpad.net/python-cinderclient/+bug/1915996>`_:
Passing client certificates for mTLS connections was not supported
and now has been fixed.