Fix CA file for Swift pollster

Most OpenStack API communication uses the cafile option in the
service_credentials config. For swift the client is created differently,
and does not get this option. When TLS is used, we may get an error like
the following:

exceptions.SSLError: HTTPSConnectionPool(host='1.2.3.4', port=443): Max
retries exceeded with url: /swift/v1/AUTH_XXXX (Caused by
SSLError(SSLError("bad handshake: Error([('SSL routines',
'tls_process_server_certificate', 'certificate verify failed')],)",),))

This change fixes the issue by creating an HTTP connection for the Swift
client that uses the configured CA file.

Closes-Bug: #1940660
Change-Id: I38f9ff2bec0a2a3cb9dfc5c362284e33c12f3127
This commit is contained in:
Mark Goddard 2021-08-20 14:23:54 +01:00
parent cb389d0c5d
commit ed404c5f66
3 changed files with 40 additions and 17 deletions

View File

@ -86,10 +86,14 @@ class _Base(plugin_base.PollsterBase):
swift_api_method = getattr(swift, '%s_account' % self.METHOD)
for t in tenants:
try:
yield (t.id, swift_api_method(
http_conn = swift.http_connection(
self._neaten_url(endpoint, t.id,
self.conf.reseller_prefix),
keystone_client.get_auth_token(ksclient)))
cacert=self.conf.service_credentials.cafile)
yield (t.id, swift_api_method(
None,
keystone_client.get_auth_token(ksclient),
http_conn))
except ClientException as e:
if e.http_status == 404:
LOG.warning("Swift tenant id %s not found.", t.id)

View File

@ -188,18 +188,27 @@ class TestSwiftPollster(testscenarios.testcase.WithScenarios,
mock_method = mock.MagicMock()
endpoint = 'end://point/'
api_method = '%s_account' % self.pollster.METHOD
mock_connection = mock.MagicMock()
with fixtures.MockPatchObject(swift_client,
api_method,
new=mock_method):
with fixtures.MockPatchObject(
self.manager._service_catalog, 'url_for',
return_value=endpoint):
list(self.pollster.get_samples(self.manager, {},
ASSIGNED_TENANTS))
with fixtures.MockPatchObject(swift_client,
'http_connection',
new=mock_connection):
with fixtures.MockPatchObject(
self.manager._service_catalog, 'url_for',
return_value=endpoint):
list(self.pollster.get_samples(self.manager, {},
ASSIGNED_TENANTS))
expected = [mock.call(self.pollster._neaten_url(
endpoint, t.id, self.CONF.reseller_prefix),
self.manager._auth_token)
for t in ASSIGNED_TENANTS]
endpoint, t.id, self.CONF.reseller_prefix),
cacert=None)
for t in ASSIGNED_TENANTS]
self.assertEqual(expected, mock_connection.call_args_list)
expected = [mock.call(None, self.manager._auth_token,
mock_connection.return_value)
for t in ASSIGNED_TENANTS]
self.assertEqual(expected, mock_method.call_args_list)
def test_get_endpoint_only_once(self):
@ -208,13 +217,16 @@ class TestSwiftPollster(testscenarios.testcase.WithScenarios,
api_method = '%s_account' % self.pollster.METHOD
with fixtures.MockPatchObject(swift_client, api_method,
new=mock.MagicMock()):
with fixtures.MockPatchObject(
self.manager._service_catalog, 'url_for',
new=mock_url_for):
list(self.pollster.get_samples(self.manager, {},
ASSIGNED_TENANTS))
list(self.pollster.get_samples(self.manager, {},
ASSIGNED_TENANTS))
with fixtures.MockPatchObject(swift_client,
'http_connection',
new=mock.MagicMock()):
with fixtures.MockPatchObject(
self.manager._service_catalog, 'url_for',
new=mock_url_for):
list(self.pollster.get_samples(self.manager, {},
ASSIGNED_TENANTS))
list(self.pollster.get_samples(self.manager, {},
ASSIGNED_TENANTS))
self.assertEqual(1, mock_url_for.call_count)
def test_endpoint_notfound(self):

View File

@ -0,0 +1,7 @@
---
fixes:
- >
[`bug 1940660 <https://bugs.launchpad.net/ceilometer/+bug/1940660>`_]
Fixes an issue with the Swift pollster where the ``[service_credentials]
cafile`` option was not used. This could prevent communication with
TLS-enabled Swift APIs.