diff options
author | Dmitry Tantsur <dtantsur@protonmail.com> | 2021-01-08 17:57:56 +0100 |
---|---|---|
committer | Dmitry Tantsur <dtantsur@protonmail.com> | 2021-01-19 17:56:06 +0100 |
commit | b6f4587f0bdfc2f4b5736db1c9f89639ef2e09a7 (patch) | |
tree | fb537867eded3c171686df7ca5b5cd41d00fff5e /ironic/drivers | |
parent | d35eb8bd0e401f659fa4190ea875251ff841a345 (diff) | |
download | ironic-b6f4587f0bdfc2f4b5736db1c9f89639ef2e09a7.tar.gz |
Common framework for configuring secure boot
Two drivers already support turning secore boot on and off,
Redfish will follow soon. This patch adds ManagementInterface
calls to get and set the secure boot state.
Story: #2008270
Task: #41561
Change-Id: I96b2697163def52618b4c051a5c85adf7d1818a5
Diffstat (limited to 'ironic/drivers')
-rw-r--r-- | ironic/drivers/base.py | 34 | ||||
-rw-r--r-- | ironic/drivers/modules/boot_mode_utils.py | 52 | ||||
-rw-r--r-- | ironic/drivers/modules/pxe_base.py | 3 |
3 files changed, 89 insertions, 0 deletions
diff --git a/ironic/drivers/base.py b/ironic/drivers/base.py index baf5a5579..7d137f9c4 100644 --- a/ironic/drivers/base.py +++ b/ironic/drivers/base.py @@ -972,6 +972,40 @@ class ManagementInterface(BaseInterface): raise exception.UnsupportedDriverExtension( driver=task.node.driver, extension='get_boot_mode') + def get_secure_boot_state(self, task): + """Get the current secure boot state for the node. + + NOTE: Not all drivers support this method. Older hardware + may not implement that. + + :param task: A task from TaskManager. + :raises: MissingParameterValue if a required parameter is missing + :raises: DriverOperationError or its derivative in case + of driver runtime error. + :raises: UnsupportedDriverExtension if secure boot is + not supported by the driver or the hardware + :returns: Boolean + """ + raise exception.UnsupportedDriverExtension( + driver=task.node.driver, extension='get_secure_boot_state') + + def set_secure_boot_state(self, task, state): + """Set the current secure boot state for the node. + + NOTE: Not all drivers support this method. Older hardware + may not implement that. + + :param task: A task from TaskManager. + :param state: A new state as a boolean. + :raises: MissingParameterValue if a required parameter is missing + :raises: DriverOperationError or its derivative in case + of driver runtime error. + :raises: UnsupportedDriverExtension if secure boot is + not supported by the driver or the hardware + """ + raise exception.UnsupportedDriverExtension( + driver=task.node.driver, extension='set_secure_boot_state') + @abc.abstractmethod def get_sensors_data(self, task): """Get sensors data method. diff --git a/ironic/drivers/modules/boot_mode_utils.py b/ironic/drivers/modules/boot_mode_utils.py index eea09d1c0..6eebe50aa 100644 --- a/ironic/drivers/modules/boot_mode_utils.py +++ b/ironic/drivers/modules/boot_mode_utils.py @@ -14,11 +14,13 @@ # under the License. from oslo_log import log as logging +from oslo_utils import excutils from ironic.common import boot_modes from ironic.common import exception from ironic.common.i18n import _ from ironic.common import utils as common_utils +from ironic.conductor import task_manager from ironic.conductor import utils as manager_utils from ironic.conf import CONF from ironic.drivers import utils as driver_utils @@ -296,3 +298,53 @@ def get_boot_mode(node): 'bios': boot_modes.LEGACY_BIOS, 'uefi': boot_modes.UEFI}) return CONF.deploy.default_boot_mode + + +@task_manager.require_exclusive_lock +def configure_secure_boot_if_needed(task): + """Configures secure boot if it has been requested for the node.""" + if not is_secure_boot_requested(task.node): + return + + try: + task.driver.management.set_secure_boot_state(task, True) + except exception.UnsupportedDriverExtension: + # TODO(dtantsur): make a failure in Xena + LOG.warning('Secure boot was requested for node %(node)s but its ' + 'management interface %(driver)s does not support it. ' + 'This warning will become an error in a future release.', + {'node': task.node.uuid, + 'driver': task.node.management_interface}) + except Exception as exc: + with excutils.save_and_reraise_exception(): + LOG.error('Failed to configure secure boot for node %(node)s: ' + '%(error)s', + {'node': task.node.uuid, 'error': exc}, + exc_info=not isinstance(exc, exception.IronicException)) + else: + LOG.info('Secure boot has been enabled for node %s', task.node.uuid) + + +@task_manager.require_exclusive_lock +def deconfigure_secure_boot_if_needed(task): + """Deconfigures secure boot if it has been requested for the node.""" + if not is_secure_boot_requested(task.node): + return + + try: + task.driver.management.set_secure_boot_state(task, False) + except exception.UnsupportedDriverExtension: + # NOTE(dtantsur): don't make it a hard failure to allow tearing down + # misconfigured nodes. + LOG.debug('Secure boot was requested for node %(node)s but its ' + 'management interface %(driver)s does not support it.', + {'node': task.node.uuid, + 'driver': task.node.management_interface}) + except Exception as exc: + with excutils.save_and_reraise_exception(): + LOG.error('Failed to deconfigure secure boot for node %(node)s: ' + '%(error)s', + {'node': task.node.uuid, 'error': exc}, + exc_info=not isinstance(exc, exception.IronicException)) + else: + LOG.info('Secure boot has been disabled for node %s', task.node.uuid) diff --git a/ironic/drivers/modules/pxe_base.py b/ironic/drivers/modules/pxe_base.py index 5d9ac49ba..0944e7d4e 100644 --- a/ironic/drivers/modules/pxe_base.py +++ b/ironic/drivers/modules/pxe_base.py @@ -133,6 +133,8 @@ class PXEBaseMixin(object): pxe_utils.clean_up_pxe_env(task, images_info, ipxe_enabled=self.ipxe_enabled) + boot_mode_utils.deconfigure_secure_boot_if_needed(task) + @METRICS.timer('PXEBaseMixin.prepare_ramdisk') def prepare_ramdisk(self, task, ramdisk_params): """Prepares the boot of Ironic ramdisk using PXE. @@ -240,6 +242,7 @@ class PXEBaseMixin(object): :returns: None """ boot_mode_utils.sync_boot_mode(task) + boot_mode_utils.configure_secure_boot_if_needed(task) node = task.node boot_option = deploy_utils.get_boot_option(node) |