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:
parent
ccf5e16773
commit
c2185469c4
@ -170,7 +170,7 @@ class AgentClient(object):
|
|||||||
@METRICS.timer('AgentClient.get_clean_steps')
|
@METRICS.timer('AgentClient.get_clean_steps')
|
||||||
def get_clean_steps(self, node, ports):
|
def get_clean_steps(self, node, ports):
|
||||||
params = {
|
params = {
|
||||||
'node': node.as_dict(),
|
'node': node.as_dict(secure=True),
|
||||||
'ports': [port.as_dict() for port in ports]
|
'ports': [port.as_dict() for port in ports]
|
||||||
}
|
}
|
||||||
return self._command(node=node,
|
return self._command(node=node,
|
||||||
@ -182,7 +182,7 @@ class AgentClient(object):
|
|||||||
def execute_clean_step(self, step, node, ports):
|
def execute_clean_step(self, step, node, ports):
|
||||||
params = {
|
params = {
|
||||||
'step': step,
|
'step': step,
|
||||||
'node': node.as_dict(),
|
'node': node.as_dict(secure=True),
|
||||||
'ports': [port.as_dict() for port in ports],
|
'ports': [port.as_dict() for port in ports],
|
||||||
'clean_version': node.driver_internal_info.get(
|
'clean_version': node.driver_internal_info.get(
|
||||||
'hardware_manager_version')
|
'hardware_manager_version')
|
||||||
|
@ -134,6 +134,15 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat):
|
|||||||
'traits': object_fields.ObjectField('TraitList', nullable=True),
|
'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):
|
def _validate_property_values(self, properties):
|
||||||
"""Check if the input of local_gb, cpus and memory_mb are valid.
|
"""Check if the input of local_gb, cpus and memory_mb are valid.
|
||||||
|
|
||||||
|
@ -43,7 +43,8 @@ class MockNode(object):
|
|||||||
}
|
}
|
||||||
self.instance_info = {}
|
self.instance_info = {}
|
||||||
|
|
||||||
def as_dict(self):
|
def as_dict(self, secure=False):
|
||||||
|
assert secure, 'agent_client must pass secure=True'
|
||||||
return {
|
return {
|
||||||
'uuid': self.uuid,
|
'uuid': self.uuid,
|
||||||
'driver_internal_info': self.driver_internal_info,
|
'driver_internal_info': self.driver_internal_info,
|
||||||
@ -245,7 +246,7 @@ class TestAgentClient(base.TestCase):
|
|||||||
self.client._command = mock.MagicMock(spec_set=[])
|
self.client._command = mock.MagicMock(spec_set=[])
|
||||||
ports = []
|
ports = []
|
||||||
expected_params = {
|
expected_params = {
|
||||||
'node': self.node.as_dict(),
|
'node': self.node.as_dict(secure=True),
|
||||||
'ports': []
|
'ports': []
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,7 +262,7 @@ class TestAgentClient(base.TestCase):
|
|||||||
step = {'priority': 10, 'step': 'erase_devices', 'interface': 'deploy'}
|
step = {'priority': 10, 'step': 'erase_devices', 'interface': 'deploy'}
|
||||||
expected_params = {
|
expected_params = {
|
||||||
'step': step,
|
'step': step,
|
||||||
'node': self.node.as_dict(),
|
'node': self.node.as_dict(secure=True),
|
||||||
'ports': [],
|
'ports': [],
|
||||||
'clean_version':
|
'clean_version':
|
||||||
self.node.driver_internal_info['hardware_manager_version']
|
self.node.driver_internal_info['hardware_manager_version']
|
||||||
|
@ -35,6 +35,20 @@ class TestNodeObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn):
|
|||||||
self.fake_node = db_utils.get_test_node()
|
self.fake_node = db_utils.get_test_node()
|
||||||
self.node = obj_utils.get_test_node(self.ctxt, **self.fake_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):
|
def test_get_by_id(self):
|
||||||
node_id = self.fake_node['id']
|
node_id = self.fake_node['id']
|
||||||
with mock.patch.object(self.dbapi, 'get_node_by_id',
|
with mock.patch.object(self.dbapi, 'get_node_by_id',
|
||||||
|
@ -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.
|
Loading…
Reference in New Issue
Block a user