From 82704e6d8d750f7a931d1b964bc246dcb2c50e38 Mon Sep 17 00:00:00 2001 From: Nikolay Fedotov Date: Tue, 5 Mar 2019 14:50:57 +0300 Subject: [PATCH] Kg key for IPMIv2 authentication Support for the -y option of ipmitool Quote from docs: -y Use supplied Kg key for IPMIv2 authentication. The key is expected in hexadecimal format and can be used to specify keys with non-printable characters. E.g. '-k PASSWORD' and '-y 50415353574F5244' are equivalent. The default is not to use any Kg key. Change-Id: Ie6a9fc1a41d924e30eff526b3eae929ce6e085c6 Story: #2005158 Task: #29876 --- ironic/drivers/modules/ipmitool.py | 13 +++++++++++++ ironic/tests/unit/conductor/test_manager.py | 2 +- ironic/tests/unit/drivers/modules/test_ipmitool.py | 14 ++++++++++++++ .../notes/ipmi_hex_kg_key-8f6caabe5b7d7a9b.yaml | 7 +++++++ 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/ipmi_hex_kg_key-8f6caabe5b7d7a9b.yaml diff --git a/ironic/drivers/modules/ipmitool.py b/ironic/drivers/modules/ipmitool.py index d759e8b75a..15a66af4e9 100644 --- a/ironic/drivers/modules/ipmitool.py +++ b/ironic/drivers/modules/ipmitool.py @@ -72,6 +72,9 @@ REQUIRED_PROPERTIES = { } OPTIONAL_PROPERTIES = { 'ipmi_password': _("password. Optional."), + 'ipmi_hex_kg_key': _('Kg key for IPMIv2 authentication. ' + 'The key is expected in hexadecimal format. ' + 'Optional.'), 'ipmi_port': _("remote IPMI RMCP port. Optional."), 'ipmi_priv_level': _("privilege level; default is ADMINISTRATOR. One of " "%s. Optional.") % ', '.join(VALID_PRIV_LEVELS), @@ -282,6 +285,7 @@ def _parse_driver_info(node): address = info.get('ipmi_address') username = info.get('ipmi_username') password = six.text_type(info.get('ipmi_password', '')) + hex_kg_key = info.get('ipmi_hex_kg_key') dest_port = info.get('ipmi_port') port = info.get('ipmi_terminal_port') priv_level = info.get('ipmi_priv_level', 'ADMINISTRATOR') @@ -361,11 +365,16 @@ def _parse_driver_info(node): " can be one of %(valid_levels)s") % {'priv_level': priv_level, 'valid_levels': valid_priv_lvls}) + if hex_kg_key and len(hex_kg_key) % 2 != 0: + raise exception.InvalidParameterValue(_( + "Number of ipmi_hex_kg_key characters is not even")) + return { 'address': address, 'dest_port': dest_port, 'username': username, 'password': password, + 'hex_kg_key': hex_kg_key, 'port': port, 'uuid': node.uuid, 'priv_level': priv_level, @@ -423,6 +432,10 @@ def _get_ipmitool_args(driver_info, pw_file=None): args.append('-U') args.append(driver_info['username']) + if driver_info['hex_kg_key']: + args.append('-y') + args.append(driver_info['hex_kg_key']) + for name, option in BRIDGING_OPTIONS: if driver_info[name] is not None: args.append(option) diff --git a/ironic/tests/unit/conductor/test_manager.py b/ironic/tests/unit/conductor/test_manager.py index 39c2a3db32..e99a156cff 100644 --- a/ironic/tests/unit/conductor/test_manager.py +++ b/ironic/tests/unit/conductor/test_manager.py @@ -7165,7 +7165,7 @@ class ManagerTestProperties(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase): 'force_persistent_boot_device', 'ipmi_protocol_version', 'ipmi_force_boot_device', 'deploy_forces_oob_reboot', 'rescue_kernel', 'rescue_ramdisk', - 'ipmi_disable_boot_timeout'] + 'ipmi_disable_boot_timeout', 'ipmi_hex_kg_key'] self._check_driver_properties("ipmi", expected) def test_driver_properties_snmp(self): diff --git a/ironic/tests/unit/drivers/modules/test_ipmitool.py b/ironic/tests/unit/drivers/modules/test_ipmitool.py index 2ba10090da..27cfdff987 100644 --- a/ironic/tests/unit/drivers/modules/test_ipmitool.py +++ b/ironic/tests/unit/drivers/modules/test_ipmitool.py @@ -779,6 +779,20 @@ class IPMIToolPrivateMethodTestCase(Base): self.assertRaises(exception.InvalidParameterValue, ipmi._parse_driver_info, node) + def test__parse_driver_info_ipmi_hex_kg_key(self): + info = dict(INFO_DICT) + info['ipmi_hex_kg_key'] = 'A115023E08E23F7F8DC4BB443A1A75F160763A43' + node = obj_utils.get_test_node(self.context, driver_info=info) + ret = ipmi._parse_driver_info(node) + self.assertEqual(info['ipmi_hex_kg_key'], ret['hex_kg_key']) + + def test__parse_driver_info_ipmi_hex_kg_key_odd_chars(self): + info = dict(INFO_DICT) + info['ipmi_hex_kg_key'] = 'A115023E08E23F7F8DC4BB443A1A75F160763A4' + node = obj_utils.get_test_node(self.context, driver_info=info) + self.assertRaises(exception.InvalidParameterValue, + ipmi._parse_driver_info, node) + def test__parse_driver_info_ipmi_port_valid(self): info = dict(INFO_DICT) info['ipmi_port'] = '623' diff --git a/releasenotes/notes/ipmi_hex_kg_key-8f6caabe5b7d7a9b.yaml b/releasenotes/notes/ipmi_hex_kg_key-8f6caabe5b7d7a9b.yaml new file mode 100644 index 0000000000..ec1aba542a --- /dev/null +++ b/releasenotes/notes/ipmi_hex_kg_key-8f6caabe5b7d7a9b.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + New property ``ipmi_hex_kg_key`` for the ipmi based interfaces. + The property enables user to set the Kg key for IPMIv2 authentication in + hexadecimal format. This value is provided to ``ipmitool`` as + the -y argument.