summaryrefslogtreecommitdiff
path: root/ironic/drivers
diff options
context:
space:
mode:
authorDmitry Tantsur <dtantsur@protonmail.com>2021-01-08 17:57:56 +0100
committerDmitry Tantsur <dtantsur@protonmail.com>2021-01-19 17:56:06 +0100
commitb6f4587f0bdfc2f4b5736db1c9f89639ef2e09a7 (patch)
treefb537867eded3c171686df7ca5b5cd41d00fff5e /ironic/drivers
parentd35eb8bd0e401f659fa4190ea875251ff841a345 (diff)
downloadironic-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.py34
-rw-r--r--ironic/drivers/modules/boot_mode_utils.py52
-rw-r--r--ironic/drivers/modules/pxe_base.py3
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)