Do not pass credentials to the ramdisk on cleaning

Currently the driver_info is passed as is to the ramdisk when calling
get_clean_steps or execute_clean_step. This may lead to their exposure,
as ironic<->ramdisk communication is currently not secure.

This change applies the same logic we use in the API to filter
the fields.

Change-Id: I4fd44786fea6c7092d2b0029cea6d680d31babde
Closes-Bug: #1744836
This commit is contained in:
Dmitry Tantsur 2018-01-23 16:13:29 +01:00
parent ccf5e16773
commit c2185469c4
5 changed files with 34 additions and 5 deletions

View File

@ -170,7 +170,7 @@ class AgentClient(object):
@METRICS.timer('AgentClient.get_clean_steps')
def get_clean_steps(self, node, ports):
params = {
'node': node.as_dict(),
'node': node.as_dict(secure=True),
'ports': [port.as_dict() for port in ports]
}
return self._command(node=node,
@ -182,7 +182,7 @@ class AgentClient(object):
def execute_clean_step(self, step, node, ports):
params = {
'step': step,
'node': node.as_dict(),
'node': node.as_dict(secure=True),
'ports': [port.as_dict() for port in ports],
'clean_version': node.driver_internal_info.get(
'hardware_manager_version')

View File

@ -134,6 +134,15 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat):
'traits': object_fields.ObjectField('TraitList', nullable=True),
}
def as_dict(self, secure=False):
d = super(Node, self).as_dict()
if secure:
d['driver_info'] = strutils.mask_dict_password(
d.get('driver_info', {}), "******")
d['instance_info'] = strutils.mask_dict_password(
d.get('instance_info', {}), "******")
return d
def _validate_property_values(self, properties):
"""Check if the input of local_gb, cpus and memory_mb are valid.

View File

@ -43,7 +43,8 @@ class MockNode(object):
}
self.instance_info = {}
def as_dict(self):
def as_dict(self, secure=False):
assert secure, 'agent_client must pass secure=True'
return {
'uuid': self.uuid,
'driver_internal_info': self.driver_internal_info,
@ -245,7 +246,7 @@ class TestAgentClient(base.TestCase):
self.client._command = mock.MagicMock(spec_set=[])
ports = []
expected_params = {
'node': self.node.as_dict(),
'node': self.node.as_dict(secure=True),
'ports': []
}
@ -261,7 +262,7 @@ class TestAgentClient(base.TestCase):
step = {'priority': 10, 'step': 'erase_devices', 'interface': 'deploy'}
expected_params = {
'step': step,
'node': self.node.as_dict(),
'node': self.node.as_dict(secure=True),
'ports': [],
'clean_version':
self.node.driver_internal_info['hardware_manager_version']

View File

@ -35,6 +35,20 @@ class TestNodeObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn):
self.fake_node = db_utils.get_test_node()
self.node = obj_utils.get_test_node(self.ctxt, **self.fake_node)
def test_as_dict_insecure(self):
self.node.driver_info['ipmi_password'] = 'fake'
self.node.instance_info['configdrive'] = 'data'
d = self.node.as_dict()
self.assertEqual('fake', d['driver_info']['ipmi_password'])
self.assertEqual('data', d['instance_info']['configdrive'])
def test_as_dict_secure(self):
self.node.driver_info['ipmi_password'] = 'fake'
self.node.instance_info['configdrive'] = 'data'
d = self.node.as_dict(secure=True)
self.assertEqual('******', d['driver_info']['ipmi_password'])
self.assertEqual('******', d['instance_info']['configdrive'])
def test_get_by_id(self):
node_id = self.fake_node['id']
with mock.patch.object(self.dbapi, 'get_node_by_id',

View File

@ -0,0 +1,5 @@
---
security:
- |
Sensitive information is now removed from a node's ``driver_info`` and
``instance_info`` fields before sending it to the ramdisk during cleaning.