Redfish: Add secure boot API support

This commit adds secure boot support via redfish APIs.
Following methods are introduced on redfish ops:

    1) get_secure_boot_mode
    2) set_secure_boot_mode
    3) clear_secure_boot_keys
    4) reset_secure_boot_keys

Co-Authored-By: Debayan Ray <debayan.ray@gmail.com>
Partial-Bug: 1691955

Change-Id: I60384a1e8093a2e926fc4341e89b559218d10d4f
This commit is contained in:
vmud213 2017-06-08 18:17:36 +05:30
parent a999200227
commit ff36d7d7d5
10 changed files with 636 additions and 5 deletions

View File

@ -78,6 +78,10 @@ SUPPORTED_REDFISH_METHODS = [
'set_pending_boot_mode', 'set_pending_boot_mode',
'reset_ilo_credential', 'reset_ilo_credential',
'reset_bios_to_default', 'reset_bios_to_default',
'get_secure_boot_mode',
'set_secure_boot_mode',
'reset_secure_boot_keys',
'clear_secure_boot_keys'
] ]
LOG = log.get_logger(__name__) LOG = log.get_logger(__name__)

View File

@ -67,7 +67,13 @@ PERSISTENT_BOOT_MAP = {
sushy.BOOT_SOURCE_TARGET_UEFI_TARGET: 'NETWORK', sushy.BOOT_SOURCE_TARGET_UEFI_TARGET: 'NETWORK',
sushy.BOOT_SOURCE_TARGET_NONE: 'NONE' sushy.BOOT_SOURCE_TARGET_NONE: 'NONE'
} }
# Assuming only one sushy_system and sushy_manager present as part of
GET_SECUREBOOT_CURRENT_BOOT_MAP = {
sys_cons.SECUREBOOT_CURRENT_BOOT_ENABLED: True,
sys_cons.SECUREBOOT_CURRENT_BOOT_DISABLED: False
}
# Assuming only one system and one manager present as part of
# collection, as we are dealing with iLO's here. # collection, as we are dealing with iLO's here.
PROLIANT_MANAGER_ID = '1' PROLIANT_MANAGER_ID = '1'
PROLIANT_SYSTEM_ID = '1' PROLIANT_SYSTEM_ID = '1'
@ -635,3 +641,106 @@ class RedfishOperations(operations.IloOperations):
{'error': str(e)}) {'error': str(e)})
LOG.debug(msg) LOG.debug(msg)
raise exception.IloError(msg) raise exception.IloError(msg)
def get_secure_boot_mode(self):
"""Get the status of secure boot.
:returns: True, if enabled, else False
:raises: IloError, on an error from iLO.
:raises: IloCommandNotSupportedError, if the command is not supported
on the server.
"""
sushy_system = self._get_sushy_system(PROLIANT_SYSTEM_ID)
try:
secure_boot_enabled = GET_SECUREBOOT_CURRENT_BOOT_MAP.get(
sushy_system.secure_boot.current_boot)
except sushy.exceptions.SushyError as e:
msg = (self._('The Redfish controller failed to provide '
'information about secure boot on the server. '
'Error: %(error)s') %
{'error': str(e)})
LOG.debug(msg)
raise exception.IloCommandNotSupportedError(msg)
if secure_boot_enabled:
LOG.debug(self._("Secure boot is Enabled"))
else:
LOG.debug(self._("Secure boot is Disabled"))
return secure_boot_enabled
def set_secure_boot_mode(self, secure_boot_enable):
"""Enable/Disable secure boot on the server.
Resetting the server post updating this settings is needed
from the caller side to make this into effect.
:param secure_boot_enable: True, if secure boot needs to be
enabled for next boot, else False.
:raises: IloError, on an error from iLO.
:raises: IloCommandNotSupportedError, if the command is not supported
on the server.
"""
if self._is_boot_mode_uefi():
sushy_system = self._get_sushy_system(PROLIANT_SYSTEM_ID)
try:
sushy_system.secure_boot.enable_secure_boot(secure_boot_enable)
except exception.InvalidInputError as e:
msg = (self._('Invalid input. Error %(error)s')
% {'error': str(e)})
LOG.debug(msg)
raise exception.IloError(msg)
except sushy.exceptions.SushyError as e:
msg = (self._('The Redfish controller failed to set secure '
'boot settings on the server. Error: %(error)s')
% {'error': str(e)})
LOG.debug(msg)
raise exception.IloError(msg)
else:
msg = (self._('System is not in UEFI boot mode. "SecureBoot" '
'related resources cannot be changed.'))
raise exception.IloCommandNotSupportedInBiosError(msg)
def reset_secure_boot_keys(self):
"""Reset secure boot keys to manufacturing defaults.
:raises: IloError, on an error from iLO.
:raises: IloCommandNotSupportedError, if the command is not supported
on the server.
"""
if self._is_boot_mode_uefi():
sushy_system = self._get_sushy_system(PROLIANT_SYSTEM_ID)
try:
sushy_system.secure_boot.reset_keys(
sys_cons.SECUREBOOT_RESET_KEYS_DEFAULT)
except sushy.exceptions.SushyError as e:
msg = (self._('The Redfish controller failed to reset secure '
'boot keys on the server. Error %(error)s')
% {'error': str(e)})
LOG.debug(msg)
raise exception.IloError(msg)
else:
msg = (self._('System is not in UEFI boot mode. "SecureBoot" '
'related resources cannot be changed.'))
raise exception.IloCommandNotSupportedInBiosError(msg)
def clear_secure_boot_keys(self):
"""Reset all keys.
:raises: IloError, on an error from iLO.
:raises: IloCommandNotSupportedError, if the command is not supported
on the server.
"""
if self._is_boot_mode_uefi():
sushy_system = self._get_sushy_system(PROLIANT_SYSTEM_ID)
try:
sushy_system.secure_boot.reset_keys(
sys_cons.SECUREBOOT_RESET_KEYS_DELETE_ALL)
except sushy.exceptions.SushyError as e:
msg = (self._('The Redfish controller failed to clear secure '
'boot keys on the server. Error %(error)s')
% {'error': str(e)})
LOG.debug(msg)
raise exception.IloError(msg)
else:
msg = (self._('System is not in UEFI boot mode. "SecureBoot" '
'related resources cannot be changed.'))
raise exception.IloCommandNotSupportedInBiosError(msg)

View File

@ -35,3 +35,14 @@ BOOT_SOURCE_TARGET_HDD = 'Hdd'
SRIOV_ENABLED = 'sriov enabled' SRIOV_ENABLED = 'sriov enabled'
SRIOV_DISABLED = 'sriov disabled' SRIOV_DISABLED = 'sriov disabled'
# Secure Boot current boot constants
SECUREBOOT_CURRENT_BOOT_ENABLED = 'enabled'
SECUREBOOT_CURRENT_BOOT_DISABLED = 'disabled'
# Secure Boot reset keys constants
SECUREBOOT_RESET_KEYS_DEFAULT = 'default'
SECUREBOOT_RESET_KEYS_DELETE_ALL = 'delete all'
SECUREBOOT_RESET_KEYS_DELETE_PK = 'delete pk'

View File

@ -41,3 +41,20 @@ SRIOV_MAP = {
'Enabled': constants.SRIOV_ENABLED, 'Enabled': constants.SRIOV_ENABLED,
'Disabled': constants.SRIOV_DISABLED 'Disabled': constants.SRIOV_DISABLED
} }
SECUREBOOT_CURRENT_BOOT_MAP = {
'Enabled': constants.SECUREBOOT_CURRENT_BOOT_ENABLED,
'Disabled': constants.SECUREBOOT_CURRENT_BOOT_DISABLED,
}
SECUREBOOT_CURRENT_BOOT_MAP_REV = (
utils.revert_dictionary(SECUREBOOT_CURRENT_BOOT_MAP))
SECUREBOOT_RESET_KEYS_MAP = {
'ResetAllKeysToDefault': constants.SECUREBOOT_RESET_KEYS_DEFAULT,
'DeleteAllKeys': constants.SECUREBOOT_RESET_KEYS_DELETE_ALL,
'DeletePK': constants.SECUREBOOT_RESET_KEYS_DELETE_PK,
}
SECUREBOOT_RESET_KEYS_MAP_REV = (
utils.revert_dictionary(SECUREBOOT_RESET_KEYS_MAP))

View File

@ -0,0 +1,120 @@
# Copyright 2017 Hewlett Packard Enterprise Development LP
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
__author__ = 'HPE'
from sushy.resources import base
from proliantutils import exception
from proliantutils import log
from proliantutils.redfish.resources.system import mappings
LOG = log.get_logger(__name__)
class ResetKeysActionField(base.CompositeField):
allowed_values = base.Field('ResetKeysType@Redfish.AllowableValues',
adapter=list)
target_uri = base.Field('target', required=True)
class ActionsField(base.CompositeField):
reset_keys = ResetKeysActionField('#SecureBoot.ResetKeys')
class SecureBoot(base.ResourceBase):
"""A class representing SecureBoot resource"""
name = base.Field('Name')
"""secure boot resource name"""
current_boot = base.MappedField(
'SecureBootCurrentBoot', mappings.SECUREBOOT_CURRENT_BOOT_MAP)
"""current secure boot"""
enable = base.Field('SecureBootEnable', required=True)
"""secure boot enable"""
# Note(deray): May need mapping if this gets used.
mode = base.Field('SecureBootMode')
"""secure boot mode"""
_actions = ActionsField('Actions', required=True)
def enable_secure_boot(self, secure_boot_enable):
"""Enable/Disable secure boot on the server.
Caller needs to reset the server after issuing this command
to bring this into effect.
:param secure_boot_enable: True, if secure boot needs to be
enabled for next boot, else False.
:raises: InvalidInputError, if the validation of the input fails
:raises: SushyError, on an error from iLO.
"""
if not isinstance(secure_boot_enable, bool):
msg = ('The parameter "%(parameter)s" value "%(value)s" is '
'invalid. Valid values are: True/False.' %
{'parameter': 'secure_boot_enable',
'value': secure_boot_enable})
raise exception.InvalidInputError(msg)
self._conn.patch(self.path,
data={'SecureBootEnable': secure_boot_enable})
def _get_reset_keys_action_element(self):
reset_keys_action = self._actions.reset_keys
if not reset_keys_action:
raise exception.MissingAttributeError(
attribute='Actions/#SecureBoot.ResetKeys',
resource=self.path)
return reset_keys_action
def get_allowed_reset_keys_values(self):
"""Get the allowed values for resetting the system.
:returns: A set with the allowed values.
"""
reset_keys_action = self._get_reset_keys_action_element()
if not reset_keys_action.allowed_values:
LOG.warning('Could not figure out the allowed values for the '
'reset keys in secure boot %s', self.path)
return set(mappings.SECUREBOOT_RESET_KEYS_MAP_REV)
return set([mappings.SECUREBOOT_RESET_KEYS_MAP[v] for v in
set(mappings.SECUREBOOT_RESET_KEYS_MAP).
intersection(reset_keys_action.allowed_values)])
def reset_keys(self, target_value):
"""Resets the secure boot keys.
:param target_value: The target value to be set.
:raises: InvalidInputError, if the target value is not
allowed.
:raises: SushyError, on an error from iLO.
"""
valid_keys_resets = self.get_allowed_reset_keys_values()
if target_value not in valid_keys_resets:
msg = ('The parameter "%(parameter)s" value "%(target_value)s" is '
'invalid. Valid values are: %(valid_keys_reset_values)s' %
{'parameter': 'target_value', 'target_value': target_value,
'valid_keys_reset_values': valid_keys_resets})
raise exception.InvalidInputError(msg)
value = mappings.SECUREBOOT_RESET_KEYS_MAP_REV[target_value]
target_uri = (
self._get_reset_keys_action_element().target_uri)
self._conn.post(target_uri, data={'ResetKeysType': value})

View File

@ -23,8 +23,10 @@ from proliantutils import log
from proliantutils.redfish.resources.system import bios from proliantutils.redfish.resources.system import bios
from proliantutils.redfish.resources.system import mappings from proliantutils.redfish.resources.system import mappings
from proliantutils.redfish.resources.system import pci_device from proliantutils.redfish.resources.system import pci_device
from proliantutils.redfish.resources.system import secure_boot
from proliantutils.redfish import utils from proliantutils.redfish import utils
LOG = log.get_logger(__name__) LOG = log.get_logger(__name__)
PERSISTENT_BOOT_DEVICE_MAP = { PERSISTENT_BOOT_DEVICE_MAP = {
@ -55,11 +57,10 @@ class HPESystem(system.System):
""" """
_hpe_actions = HpeActionsField(['Oem', 'Hpe', 'Actions'], required=True) _hpe_actions = HpeActionsField(['Oem', 'Hpe', 'Actions'], required=True)
"""Oem specific system extensibility actions""" """Oem specific system extensibility actions"""
_bios_settings = None _bios_settings = None # ref to BIOSSettings instance
_secure_boot = None # ref to SecureBoot instance
_pci_devices = None _pci_devices = None
def _get_hpe_push_power_button_action_element(self): def _get_hpe_push_power_button_action_element(self):
@ -95,7 +96,7 @@ class HPESystem(system.System):
@property @property
def bios_settings(self): def bios_settings(self):
"""Property to provide reference to bios_settings instance """Property to provide reference to `BIOSSettings` instance
It is calculated once when the first time it is queried. On refresh, It is calculated once when the first time it is queried. On refresh,
this property gets reset. this property gets reset.
@ -158,6 +159,22 @@ class HPESystem(system.System):
self, ['Oem', 'Hpe', 'Links', 'PCIDevices'])) self, ['Oem', 'Hpe', 'Links', 'PCIDevices']))
return self._pci_devices return self._pci_devices
@property
def secure_boot(self):
"""Property to provide reference to `SecureBoot` instance
It is calculated once when the first time it is queried. On refresh,
this property gets reset.
"""
if self._secure_boot is None:
self._secure_boot = secure_boot.SecureBoot(
self._conn, utils.get_subresource_path_by(self, 'SecureBoot'),
redfish_version=self.redfish_version)
return self._secure_boot
def refresh(self): def refresh(self):
super(HPESystem, self).refresh() super(HPESystem, self).refresh()
self._bios_settings = None
self._pci_devices = None self._pci_devices = None
self._secure_boot = None

View File

@ -0,0 +1,23 @@
{
"default": {
"@odata.context": "/redfish/v1/$metadata#Systems/1/SecureBoot",
"@odata.id": "/redfish/v1/Systems/1/SecureBoot",
"@odata.type": "#SecureBoot.v1_0_0.SecureBoot",
"Id": "SecureBoot",
"Name": "UEFI Secure Boot",
"Actions": {
"#SecureBoot.ResetKeys": {
"target": "/redfish/v1/Systems/1/SecureBoot/Actions/SecureBoot.ResetKeys",
"ResetKeysType@Redfish.AllowableValues": [
"ResetAllKeysToDefault",
"DeleteAllKeys",
"DeletePK"
]
},
"Oem": {}
},
"SecureBootEnable": false,
"SecureBootCurrentBoot": "Disabled",
"SecureBootMode": "UserMode"
}
}

View File

@ -0,0 +1,106 @@
# Copyright 2017 Hewlett Packard Enterprise Development LP
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import json
import mock
import testtools
from proliantutils import exception
from proliantutils.redfish.resources.system import constants as sys_cons
from proliantutils.redfish.resources.system import secure_boot
class SecureBootTestCase(testtools.TestCase):
def setUp(self):
super(SecureBootTestCase, self).setUp()
self.conn = mock.MagicMock()
with open('proliantutils/tests/redfish/'
'json_samples/secure_boot.json', 'r') as f:
self.conn.get.return_value.json.return_value = (
json.loads(f.read())['default'])
self.secure_boot_inst = secure_boot.SecureBoot(
self.conn, '/redfish/v1/Systems/1/SecureBoot',
redfish_version='1.0.2')
def test_field_attributes(self):
self.assertEqual('UEFI Secure Boot', self.secure_boot_inst.name)
self.assertEqual(sys_cons.SECUREBOOT_CURRENT_BOOT_DISABLED,
self.secure_boot_inst.current_boot)
self.assertFalse(self.secure_boot_inst.enable)
self.assertEqual('UserMode', self.secure_boot_inst.mode)
def test_enable_secure_boot(self):
self.secure_boot_inst.enable_secure_boot(True)
self.secure_boot_inst._conn.patch.assert_called_once_with(
'/redfish/v1/Systems/1/SecureBoot',
data={'SecureBootEnable': True})
def test_enable_secure_boot_invalid_value(self):
self.assertRaisesRegex(
exception.InvalidInputError,
'The parameter "secure_boot_enable" value "some-non-boolean" is '
'invalid. Valid values are: True/False.',
self.secure_boot_inst.enable_secure_boot, 'some-non-boolean')
def test__get_reset_keys_action_element(self):
value = self.secure_boot_inst._get_reset_keys_action_element()
self.assertEqual('/redfish/v1/Systems/1/SecureBoot/Actions/'
'SecureBoot.ResetKeys',
value.target_uri)
self.assertEqual(['ResetAllKeysToDefault',
'DeleteAllKeys',
'DeletePK'], value.allowed_values)
def test__get_reset_keys_action_element_missing_action(self):
self.secure_boot_inst._actions.reset_keys = None
self.assertRaisesRegex(
exception.MissingAttributeError,
'Actions/#SecureBoot.ResetKeys is missing',
self.secure_boot_inst._get_reset_keys_action_element)
def test_get_allowed_reset_keys_values(self):
values = self.secure_boot_inst.get_allowed_reset_keys_values()
expected = set([sys_cons.SECUREBOOT_RESET_KEYS_DEFAULT,
sys_cons.SECUREBOOT_RESET_KEYS_DELETE_ALL,
sys_cons.SECUREBOOT_RESET_KEYS_DELETE_PK])
self.assertEqual(expected, values)
self.assertIsInstance(values, set)
@mock.patch.object(secure_boot.LOG, 'warning', autospec=True)
def test_get_allowed_reset_keys_values_no_values_specified(
self, mock_log):
self.secure_boot_inst._actions.reset_keys.allowed_values = None
values = self.secure_boot_inst.get_allowed_reset_keys_values()
# Assert it returns all values if it can't get the specific ones
expected = set([sys_cons.SECUREBOOT_RESET_KEYS_DEFAULT,
sys_cons.SECUREBOOT_RESET_KEYS_DELETE_ALL,
sys_cons.SECUREBOOT_RESET_KEYS_DELETE_PK])
self.assertEqual(expected, values)
self.assertIsInstance(values, set)
self.assertEqual(1, mock_log.call_count)
def test_reset_keys(self):
self.secure_boot_inst.reset_keys(
sys_cons.SECUREBOOT_RESET_KEYS_DEFAULT)
self.secure_boot_inst._conn.post.assert_called_once_with(
'/redfish/v1/Systems/1/SecureBoot/Actions/SecureBoot.ResetKeys',
data={'ResetKeysType': 'ResetAllKeysToDefault'})
def test_reset_keys_invalid_value(self):
self.assertRaises(exception.InvalidInputError,
self.secure_boot_inst.reset_keys, 'invalid-value')

View File

@ -22,6 +22,7 @@ import testtools
from proliantutils import exception from proliantutils import exception
from proliantutils.redfish.resources.system import bios from proliantutils.redfish.resources.system import bios
from proliantutils.redfish.resources.system import constants as sys_cons from proliantutils.redfish.resources.system import constants as sys_cons
from proliantutils.redfish.resources.system import secure_boot
from proliantutils.redfish.resources.system import system from proliantutils.redfish.resources.system import system
from sushy.resources.system import system as sushy_system from sushy.resources.system import system as sushy_system
@ -106,6 +107,33 @@ class HPESystemTestCase(testtools.TestCase):
sushy.BOOT_SOURCE_TARGET_CD, sushy.BOOT_SOURCE_TARGET_CD,
enabled=sushy.BOOT_SOURCE_ENABLED_ONCE) enabled=sushy.BOOT_SOURCE_ENABLED_ONCE)
def test_bios_settings_on_refresh(self):
# | GIVEN |
with open('proliantutils/tests/redfish/json_samples/bios.json',
'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN & THEN |
self.assertIsInstance(self.sys_inst.bios_settings,
bios.BIOSSettings)
# On refreshing the system instance...
with open('proliantutils/tests/redfish/'
'json_samples/system.json', 'r') as f:
self.conn.get.return_value.json.return_value = (
json.loads(f.read())['default'])
self.sys_inst.refresh()
# | WHEN & THEN |
self.assertIsNone(self.sys_inst._bios_settings)
# | GIVEN |
with open('proliantutils/tests/redfish/json_samples/bios.json',
'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN & THEN |
self.assertIsInstance(self.sys_inst.bios_settings,
bios.BIOSSettings)
def test_update_persistent_boot_uefi_target(self): def test_update_persistent_boot_uefi_target(self):
with open('proliantutils/tests/redfish/' with open('proliantutils/tests/redfish/'
'json_samples/bios.json', 'r') as f: 'json_samples/bios.json', 'r') as f:
@ -169,3 +197,66 @@ class HPESystemTestCase(testtools.TestCase):
self.assertIs(actual_pci, self.assertIs(actual_pci,
self.sys_inst.pci_devices) self.sys_inst.pci_devices)
self.conn.get.return_value.json.assert_not_called() self.conn.get.return_value.json.assert_not_called()
def test_secure_boot_with_missing_path_attr(self):
def _get_secure_boot():
return self.sys_inst.secure_boot
self.sys_inst._json.pop('SecureBoot')
self.assertRaisesRegex(
exception.MissingAttributeError,
'attribute SecureBoot is missing',
_get_secure_boot)
def test_secure_boot(self):
# check for the underneath variable value
self.assertIsNone(self.sys_inst._secure_boot)
# | GIVEN |
self.conn.get.return_value.json.reset_mock()
with open('proliantutils/tests/redfish/json_samples/secure_boot.json',
'r') as f:
self.conn.get.return_value.json.return_value = (
json.loads(f.read())['default'])
# | WHEN |
actual_secure_boot = self.sys_inst.secure_boot
# | THEN |
self.assertIsInstance(actual_secure_boot,
secure_boot.SecureBoot)
self.conn.get.return_value.json.assert_called_once_with()
# reset mock
self.conn.get.return_value.json.reset_mock()
# | WHEN & THEN |
# tests for same object on invoking subsequently
self.assertIs(actual_secure_boot,
self.sys_inst.secure_boot)
self.conn.get.return_value.json.assert_not_called()
def test_secure_boot_on_refresh(self):
# | GIVEN |
with open('proliantutils/tests/redfish/json_samples/secure_boot.json',
'r') as f:
self.conn.get.return_value.json.return_value = (
json.loads(f.read())['default'])
# | WHEN & THEN |
self.assertIsInstance(self.sys_inst.secure_boot,
secure_boot.SecureBoot)
# On refreshing the system instance...
with open('proliantutils/tests/redfish/'
'json_samples/system.json', 'r') as f:
self.conn.get.return_value.json.return_value = (
json.loads(f.read())['default'])
self.sys_inst.refresh()
# | WHEN & THEN |
self.assertIsNone(self.sys_inst._secure_boot)
# | GIVEN |
with open('proliantutils/tests/redfish/json_samples/secure_boot.json',
'r') as f:
self.conn.get.return_value.json.return_value = (
json.loads(f.read())['default'])
# | WHEN & THEN |
self.assertIsInstance(self.sys_inst.secure_boot,
secure_boot.SecureBoot)

View File

@ -717,3 +717,136 @@ class RedfishOperationsTestCase(testtools.TestCase):
exception.IloError, exception.IloError,
"The Redfish controller is unable to update bios settings" "The Redfish controller is unable to update bios settings"
" to default", self.rf_client.reset_bios_to_default) " to default", self.rf_client.reset_bios_to_default)
@mock.patch.object(redfish.LOG, 'debug', autospec=True)
def test_get_secure_boot_mode(self, log_debug_mock):
sushy_system_mock = self.sushy.get_system.return_value
type(sushy_system_mock.secure_boot).current_boot = mock.PropertyMock(
return_value=sys_cons.SECUREBOOT_CURRENT_BOOT_ENABLED)
self.rf_client.get_secure_boot_mode()
log_debug_mock.assert_called_once_with(
'[iLO 1.2.3.4] Secure boot is Enabled')
log_debug_mock.reset_mock()
type(sushy_system_mock.secure_boot).current_boot = mock.PropertyMock(
return_value=sys_cons.SECUREBOOT_CURRENT_BOOT_DISABLED)
self.rf_client.get_secure_boot_mode()
log_debug_mock.assert_called_once_with(
'[iLO 1.2.3.4] Secure boot is Disabled')
def test_get_secure_boot_mode_on_fail(self):
sushy_system_mock = self.sushy.get_system.return_value
type(sushy_system_mock).secure_boot = mock.PropertyMock(
side_effect=sushy.exceptions.SushyError)
self.assertRaisesRegex(
exception.IloCommandNotSupportedError,
'The Redfish controller failed to provide '
'information about secure boot on the server.',
self.rf_client.get_secure_boot_mode)
@mock.patch.object(redfish.RedfishOperations, '_is_boot_mode_uefi',
autospec=True)
def test_set_secure_boot_mode(self, _is_boot_mode_uefi_mock):
_is_boot_mode_uefi_mock.return_value = True
self.rf_client.set_secure_boot_mode(True)
secure_boot_mock = self.sushy.get_system.return_value.secure_boot
secure_boot_mock.enable_secure_boot.assert_called_once_with(True)
@mock.patch.object(redfish.RedfishOperations, '_is_boot_mode_uefi',
autospec=True)
def test_set_secure_boot_mode_in_bios(self, _is_boot_mode_uefi_mock):
_is_boot_mode_uefi_mock.return_value = False
self.assertRaisesRegex(
exception.IloCommandNotSupportedInBiosError,
'System is not in UEFI boot mode. "SecureBoot" related resources '
'cannot be changed.',
self.rf_client.set_secure_boot_mode, True)
@mock.patch.object(redfish.RedfishOperations, '_is_boot_mode_uefi',
autospec=True)
def test_set_secure_boot_mode_on_fail(self, _is_boot_mode_uefi_mock):
_is_boot_mode_uefi_mock.return_value = True
secure_boot_mock = self.sushy.get_system.return_value.secure_boot
secure_boot_mock.enable_secure_boot.side_effect = (
sushy.exceptions.SushyError)
self.assertRaisesRegex(
exception.IloError,
'The Redfish controller failed to set secure boot settings '
'on the server.',
self.rf_client.set_secure_boot_mode, True)
@mock.patch.object(redfish.RedfishOperations, '_is_boot_mode_uefi',
autospec=True)
def test_set_secure_boot_mode_for_invalid_value(
self, _is_boot_mode_uefi_mock):
_is_boot_mode_uefi_mock.return_value = True
secure_boot_mock = self.sushy.get_system.return_value.secure_boot
secure_boot_mock.enable_secure_boot.side_effect = (
exception.InvalidInputError('Invalid input'))
self.assertRaises(
exception.IloError,
self.rf_client.set_secure_boot_mode, 'some-non-boolean')
@mock.patch.object(redfish.RedfishOperations, '_is_boot_mode_uefi',
autospec=True)
def test_reset_secure_boot_keys(self, _is_boot_mode_uefi_mock):
_is_boot_mode_uefi_mock.return_value = True
self.rf_client.reset_secure_boot_keys()
sushy_system_mock = self.sushy.get_system.return_value
sushy_system_mock.secure_boot.reset_keys.assert_called_once_with(
sys_cons.SECUREBOOT_RESET_KEYS_DEFAULT)
@mock.patch.object(redfish.RedfishOperations, '_is_boot_mode_uefi',
autospec=True)
def test_reset_secure_boot_keys_in_bios(self, _is_boot_mode_uefi_mock):
_is_boot_mode_uefi_mock.return_value = False
self.assertRaisesRegex(
exception.IloCommandNotSupportedInBiosError,
'System is not in UEFI boot mode. "SecureBoot" related resources '
'cannot be changed.',
self.rf_client.reset_secure_boot_keys)
@mock.patch.object(redfish.RedfishOperations, '_is_boot_mode_uefi',
autospec=True)
def test_reset_secure_boot_keys_on_fail(self, _is_boot_mode_uefi_mock):
_is_boot_mode_uefi_mock.return_value = True
sushy_system_mock = self.sushy.get_system.return_value
sushy_system_mock.secure_boot.reset_keys.side_effect = (
sushy.exceptions.SushyError)
self.assertRaisesRegex(
exception.IloError,
'The Redfish controller failed to reset secure boot keys '
'on the server.',
self.rf_client.reset_secure_boot_keys)
@mock.patch.object(redfish.RedfishOperations, '_is_boot_mode_uefi',
autospec=True)
def test_clear_secure_boot_keys(self, _is_boot_mode_uefi_mock):
_is_boot_mode_uefi_mock.return_value = True
self.rf_client.clear_secure_boot_keys()
sushy_system_mock = self.sushy.get_system.return_value
sushy_system_mock.secure_boot.reset_keys.assert_called_once_with(
sys_cons.SECUREBOOT_RESET_KEYS_DELETE_ALL)
@mock.patch.object(redfish.RedfishOperations, '_is_boot_mode_uefi',
autospec=True)
def test_clear_secure_boot_keys_in_bios(self, _is_boot_mode_uefi_mock):
_is_boot_mode_uefi_mock.return_value = False
self.assertRaisesRegex(
exception.IloCommandNotSupportedInBiosError,
'System is not in UEFI boot mode. "SecureBoot" related resources '
'cannot be changed.',
self.rf_client.clear_secure_boot_keys)
@mock.patch.object(redfish.RedfishOperations, '_is_boot_mode_uefi',
autospec=True)
def test_clear_secure_boot_keys_on_fail(self, _is_boot_mode_uefi_mock):
_is_boot_mode_uefi_mock.return_value = True
sushy_system_mock = self.sushy.get_system.return_value
sushy_system_mock.secure_boot.reset_keys.side_effect = (
sushy.exceptions.SushyError)
self.assertRaisesRegex(
exception.IloError,
'The Redfish controller failed to clear secure boot keys '
'on the server.',
self.rf_client.clear_secure_boot_keys)