Expose agent_verify_ca in configuration and correctly handle booleans

Currently "False" will likely be treated as a path.

Story: #2007214
Task: #40944
Change-Id: I37736b8aa34b86de6223b47812f5d544e3e0a73d
This commit is contained in:
Dmitry Tantsur 2020-09-23 15:01:45 +02:00
parent 19d910db40
commit cb8cc0ca65
3 changed files with 85 additions and 7 deletions

View File

@ -151,8 +151,14 @@ opts = [
'be rejected by the conductor.')),
cfg.StrOpt('certificates_path',
default='/var/lib/ironic/certificates',
help=_('Path for TLS certificates used to validate '
'connections to the ramdisk.')),
help=_('Path to store auto-generated TLS certificates used to '
'validate connections to the ramdisk.')),
cfg.StrOpt('verify_ca',
default='True',
help=_('Path to the TLS CA to validate connection to the '
'ramdisk. Set to True to use the system default CA '
'storage. Set to False to disable validation. Ignored '
'when automatic TLS setup is used.')),
]

View File

@ -13,10 +13,12 @@
# limitations under the License.
from http import client as http_client
import os
from ironic_lib import metrics_utils
from oslo_log import log
from oslo_serialization import jsonutils
from oslo_utils import strutils
import requests
import retrying
@ -77,8 +79,18 @@ class AgentClient(object):
})
def _get_verify(self, node):
return (node.driver_internal_info.get('agent_verify_ca')
or node.driver_info.get('agent_verify_ca', True))
value = (node.driver_internal_info.get('agent_verify_ca')
or node.driver_info.get('agent_verify_ca')
or CONF.agent.verify_ca)
if isinstance(value, str):
try:
value = strutils.bool_from_string(value, strict=True)
except ValueError:
if not os.path.exists(value):
raise exception.InvalidParameterValue(
_('Agent CA %s is neither a path nor a boolean')
% value)
return value
def _raise_if_typeerror(self, result, node, method):
error = result.get('command_error')

View File

@ -237,7 +237,8 @@ class TestAgentClient(base.TestCase):
timeout=60,
verify=True)
def test__command_verify(self):
@mock.patch('os.path.exists', autospec=True, return_value=True)
def test__command_verify(self, mock_exists):
response_data = {'status': 'ok'}
self.client.session.post.return_value = MockResponse(response_data)
method = 'standby.run_image'
@ -258,7 +259,8 @@ class TestAgentClient(base.TestCase):
timeout=60,
verify='/path/to/agent.crt')
def test__command_verify_internal(self):
@mock.patch('os.path.exists', autospec=True, return_value=True)
def test__command_verify_internal(self, mock_exists):
response_data = {'status': 'ok'}
self.client.session.post.return_value = MockResponse(response_data)
method = 'standby.run_image'
@ -280,6 +282,63 @@ class TestAgentClient(base.TestCase):
timeout=60,
verify='/path/to/crt')
@mock.patch('os.path.exists', autospec=True, return_value=True)
def test__command_verify_config(self, mock_exists):
response_data = {'status': 'ok'}
self.client.session.post.return_value = MockResponse(response_data)
method = 'standby.run_image'
image_info = {'image_id': 'test_image'}
params = {'image_info': image_info}
self.config(verify_ca='/path/to/crt', group='agent')
url = self.client._get_command_url(self.node)
body = self.client._get_command_body(method, params)
response = self.client._command(self.node, method, params)
self.assertEqual(response, response_data)
self.client.session.post.assert_called_once_with(
url,
data=body,
params={'wait': 'false'},
timeout=60,
verify='/path/to/crt')
@mock.patch('os.path.exists', autospec=True, return_value=True)
def test__command_verify_disable(self, mock_exists):
response_data = {'status': 'ok'}
self.client.session.post.return_value = MockResponse(response_data)
method = 'standby.run_image'
image_info = {'image_id': 'test_image'}
params = {'image_info': image_info}
self.config(verify_ca='False', group='agent')
url = self.client._get_command_url(self.node)
body = self.client._get_command_body(method, params)
response = self.client._command(self.node, method, params)
self.assertEqual(response, response_data)
self.client.session.post.assert_called_once_with(
url,
data=body,
params={'wait': 'false'},
timeout=60,
verify=False)
@mock.patch('os.path.exists', autospec=True, return_value=False)
def test__command_verify_invalid_file(self, mock_exists):
response_data = {'status': 'ok'}
self.client.session.post.return_value = MockResponse(response_data)
method = 'standby.run_image'
image_info = {'image_id': 'test_image'}
params = {'image_info': image_info}
self.config(verify_ca='/path/to/crt', group='agent')
self.assertRaises(exception.InvalidParameterValue,
self.client._command, self.node, method, params)
@mock.patch('time.sleep', lambda seconds: None)
def test__command_poll(self):
response_data = {'status': 'ok'}
@ -344,7 +403,8 @@ class TestAgentClient(base.TestCase):
retry_connection=False)
self.assertEqual(1, self.client.session.get.call_count)
def test_get_commands_status_verify(self):
@mock.patch('os.path.exists', autospec=True, return_value=True)
def test_get_commands_status_verify(self, mock_exists):
self.node.driver_info['agent_verify_ca'] = '/path/to/agent.crt'
with mock.patch.object(self.client.session, 'get',