workaround: requests verify handling if env is set

if the env REQUESTS_CA_BUNDLE is set the requests.Session() ignores the
verify parameter. Therefore the verify parameter is moved directly into
the function call of request.

Workaround for https://github.com/psf/requests/issues/3829

Change-Id: I66dc7c4d90e5bd5e3d1b331cf1728f27dece6dd4
This commit is contained in:
Samuel Kunkel 2023-01-18 09:43:52 +01:00
parent a330427d94
commit 98c899997f
3 changed files with 29 additions and 10 deletions

View File

@ -0,0 +1,9 @@
---
fixes:
- |
Workaround for https://github.com/psf/requests/issues/3829
If the env ``REQUESTS_CA_BUNDLE`` is set the ``requests.Session()``
ignores the verify parameter. Therefore the verify parameter
is moved directly into the function call of requests.

View File

@ -20,6 +20,7 @@ import time
from urllib import parse as urlparse from urllib import parse as urlparse
import requests import requests
from urllib3.exceptions import InsecureRequestWarning
from sushy import exceptions from sushy import exceptions
from sushy.taskmonitor import TaskMonitor from sushy.taskmonitor import TaskMonitor
@ -37,7 +38,6 @@ class Connector(object):
self._url = url self._url = url
self._verify = verify self._verify = verify
self._session = requests.Session() self._session = requests.Session()
self._session.verify = self._verify
self._response_callback = response_callback self._response_callback = response_callback
self._auth = None self._auth = None
self._server_side_retries = server_side_retries self._server_side_retries = server_side_retries
@ -68,6 +68,13 @@ class Connector(object):
'be removed in the future') 'be removed in the future')
self.set_http_basic_auth(username, password) self.set_http_basic_auth(username, password)
if not self._verify:
# As the user specifically needs to opt out of certificate
# validation the user is aware of the security implications
# and does not need to be overwhelmed by the urllib3 warnings
requests.packages.urllib3.disable_warnings(
category=InsecureRequestWarning)
def set_auth(self, auth): def set_auth(self, auth):
"""Sets the authentication mechanism for our connector.""" """Sets the authentication mechanism for our connector."""
self._auth = auth self._auth = auth
@ -140,6 +147,7 @@ class Connector(object):
try: try:
response = self._session.request(method, url, json=data, response = self._session.request(method, url, json=data,
headers=headers, headers=headers,
verify=self._verify,
**extra_session_req_kwargs) **extra_session_req_kwargs)
except requests.exceptions.RequestException as e: except requests.exceptions.RequestException as e:
# Capture any general exception by looking for the parent # Capture any general exception by looking for the parent
@ -197,6 +205,7 @@ class Connector(object):
response = self._session.request( response = self._session.request(
method, url, json=data, method, url, json=data,
headers=headers, headers=headers,
verify=self._verify,
**extra_session_req_kwargs) **extra_session_req_kwargs)
except exceptions.HTTPError as retry_exc: except exceptions.HTTPError as retry_exc:
LOG.error("Failure occured while attempting to retry " LOG.error("Failure occured while attempting to retry "

View File

@ -178,7 +178,7 @@ class ConnectorOpTestCase(base.TestCase):
self.conn._op('GET', path='fake/path', headers=self.headers) self.conn._op('GET', path='fake/path', headers=self.headers)
self.request.assert_called_once_with( self.request.assert_called_once_with(
'GET', 'http://foo.bar:1234/fake/path', 'GET', 'http://foo.bar:1234/fake/path',
headers=self.headers, json=None) headers=self.headers, json=None, verify=True)
def test_response_callback(self): def test_response_callback(self):
mock_response_callback = mock.MagicMock() mock_response_callback = mock.MagicMock()
@ -192,21 +192,22 @@ class ConnectorOpTestCase(base.TestCase):
allow_redirects=False) allow_redirects=False)
self.request.assert_called_once_with( self.request.assert_called_once_with(
'GET', 'http://foo.bar:1234/fake/path', 'GET', 'http://foo.bar:1234/fake/path',
headers=self.headers, json=None, allow_redirects=False) headers=self.headers, json=None, allow_redirects=False,
verify=True)
def test_ok_post(self): def test_ok_post(self):
self.conn._op('POST', path='fake/path', data=self.data.copy(), self.conn._op('POST', path='fake/path', data=self.data.copy(),
headers=self.headers) headers=self.headers)
self.request.assert_called_once_with( self.request.assert_called_once_with(
'POST', 'http://foo.bar:1234/fake/path', 'POST', 'http://foo.bar:1234/fake/path',
json=self.data, headers=self.headers) json=self.data, headers=self.headers, verify=True)
def test_ok_put(self): def test_ok_put(self):
self.conn._op('PUT', path='fake/path', data=self.data.copy(), self.conn._op('PUT', path='fake/path', data=self.data.copy(),
headers=self.headers) headers=self.headers)
self.request.assert_called_once_with( self.request.assert_called_once_with(
'PUT', 'http://foo.bar:1234/fake/path', 'PUT', 'http://foo.bar:1234/fake/path',
json=self.data, headers=self.headers) json=self.data, headers=self.headers, verify=True)
def test_ok_delete(self): def test_ok_delete(self):
expected_headers = self.headers.copy() expected_headers = self.headers.copy()
@ -214,7 +215,7 @@ class ConnectorOpTestCase(base.TestCase):
self.conn._op('DELETE', path='fake/path', headers=self.headers.copy()) self.conn._op('DELETE', path='fake/path', headers=self.headers.copy())
self.request.assert_called_once_with( self.request.assert_called_once_with(
'DELETE', 'http://foo.bar:1234/fake/path', 'DELETE', 'http://foo.bar:1234/fake/path',
headers=expected_headers, json=None) headers=expected_headers, json=None, verify=True)
def test_ok_post_with_session(self): def test_ok_post_with_session(self):
self.conn._session.headers = {} self.conn._session.headers = {}
@ -226,7 +227,7 @@ class ConnectorOpTestCase(base.TestCase):
data=self.data) data=self.data)
self.request.assert_called_once_with( self.request.assert_called_once_with(
'POST', 'http://foo.bar:1234/fake/path', 'POST', 'http://foo.bar:1234/fake/path',
json=self.data, headers=expected_headers) json=self.data, headers=expected_headers, verify=True)
self.assertEqual(self.conn._session.headers, self.assertEqual(self.conn._session.headers,
{'X-Auth-Token': 'asdf1234'}) {'X-Auth-Token': 'asdf1234'})
@ -239,7 +240,7 @@ class ConnectorOpTestCase(base.TestCase):
self.conn._op('GET', path=path, headers=headers) self.conn._op('GET', path=path, headers=headers)
self.request.assert_called_once_with( self.request.assert_called_once_with(
'GET', 'http://foo.bar:1234' + path, 'GET', 'http://foo.bar:1234' + path,
headers=expected_headers, json=None) headers=expected_headers, json=None, verify=True)
def test_odata_version_header_redfish_no_headers(self): def test_odata_version_header_redfish_no_headers(self):
path = '/redfish/v1/bar' path = '/redfish/v1/bar'
@ -247,7 +248,7 @@ class ConnectorOpTestCase(base.TestCase):
self.conn._op('GET', path=path) self.conn._op('GET', path=path)
self.request.assert_called_once_with( self.request.assert_called_once_with(
'GET', 'http://foo.bar:1234' + path, 'GET', 'http://foo.bar:1234' + path,
headers=expected_headers, json=None) headers=expected_headers, json=None, verify=True)
def test_odata_version_header_redfish_existing_header(self): def test_odata_version_header_redfish_existing_header(self):
path = '/redfish/v1/foo' path = '/redfish/v1/foo'
@ -256,7 +257,7 @@ class ConnectorOpTestCase(base.TestCase):
self.conn._op('GET', path=path, headers=headers) self.conn._op('GET', path=path, headers=headers)
self.request.assert_called_once_with( self.request.assert_called_once_with(
'GET', 'http://foo.bar:1234' + path, 'GET', 'http://foo.bar:1234' + path,
headers=expected_headers, json=None) headers=expected_headers, json=None, verify=True)
def test_timed_out_session_unable_to_create_session(self): def test_timed_out_session_unable_to_create_session(self):
self.conn._auth.can_refresh_session.return_value = False self.conn._auth.can_refresh_session.return_value = False