sushy/sushy/resources/system/secure_boot.py

150 lines
5.4 KiB
Python

# 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.
# This is referred from Redfish standard schema.
# http://redfish.dmtf.org/schemas/v1/SecureBoot.v1_1_0.json
import logging
from sushy import exceptions
from sushy.resources import base
from sushy.resources import common
from sushy.resources.system import constants
from sushy.resources.system import secure_boot_database
from sushy import utils
LOG = logging.getLogger(__name__)
class ResetKeysActionField(common.ActionField):
allowed_values = base.Field('ResetKeysType@Redfish.AllowableValues',
adapter=list)
class ActionsField(base.CompositeField):
reset_keys = ResetKeysActionField('#SecureBoot.ResetKeys')
"""Action that resets the UEFI Secure Boot keys."""
class SecureBoot(base.ResourceBase):
identity = base.Field('Id', required=True)
"""The Bios resource identity string"""
name = base.Field('Name')
"""The name of the resource"""
description = base.Field('Description')
"""Human-readable description of the BIOS resource"""
current_boot = base.MappedField('SecureBootCurrentBoot',
constants.SecureBootCurrentBoot)
"""The UEFI Secure Boot state during the current boot cycle."""
enabled = base.Field('SecureBootEnable')
"""Whether the UEFI Secure Boot takes effect on next boot.
This property can be enabled in UEFI boot mode only.
"""
mode = base.MappedField('SecureBootMode', constants.SecureBootMode)
"""The current UEFI Secure Boot Mode."""
# TODO(dtantsur): SecureBootDatabases
_actions = ActionsField('Actions')
def __init__(self, connector, path, redfish_version=None, registries=None,
root=None):
"""A class representing secure boot settings.
:param connector: A Connector instance
:param path: Sub-URI path to the SecureBoot resource
:param registries: Dict of message registries to be used when
parsing messages of attribute update status
:param root: Sushy root object. Empty for Sushy root itself.
"""
super().__init__(connector, path, redfish_version=redfish_version,
registries=registries, root=root)
@property
@utils.cache_it
def databases(self):
"""A collection of secure boot databases.
It is set once when the first time it is queried. On refresh,
this property is marked as stale (greedy-refresh not done).
Here the actual refresh of the sub-resource happens, if stale.
:raises: MissingAttributeError if 'SecureBootDatabases/@odata.id' field
is missing.
:returns: `SimpleStorageCollection` instance
"""
return secure_boot_database.SecureBootDatabaseCollection(
self._conn, utils.get_sub_resource_path_by(
self, "SecureBootDatabases"),
redfish_version=self.redfish_version,
registries=self.registries, root=self.root)
def _get_reset_action_element(self):
reset_action = self._actions.reset_keys
if not reset_action:
raise exceptions.MissingActionError(action='#SecureBoot.ResetKeys',
resource=self._path)
return reset_action
def get_allowed_reset_keys_values(self):
"""Get the allowed values for resetting the keys.
:returns: A set with the allowed values.
"""
reset_action = self._get_reset_action_element()
if not reset_action.allowed_values:
LOG.warning('Could not figure out the allowed values for the '
'reset keys action for %s', self.identity)
return set(constants.SecureBootResetKeysType)
return {v for v in constants.SecureBootResetKeysType
if v.value in reset_action.allowed_values}
def reset_keys(self, reset_type):
"""Reset secure boot keys.
:param reset_type: Reset type, one of `SECURE_BOOT_RESET_KEYS_*`
constants.
"""
valid_resets = self.get_allowed_reset_keys_values()
if reset_type not in valid_resets:
raise exceptions.InvalidParameterValueError(
parameter='reset_type', value=reset_type,
valid_values=valid_resets)
reset_type = constants.SecureBootResetKeysType(reset_type).value
target_uri = self._get_reset_action_element().target_uri
self._conn.post(target_uri, data={'ResetKeysType': reset_type})
def set_enabled(self, enabled):
"""Enable/disable secure boot.
:param enabled: True, if secure boot is enabled for next boot.
"""
if not isinstance(enabled, bool):
raise exceptions.InvalidParameterValueError(
"Expected a boolean for 'enabled', got %r" % enabled)
etag = self._get_etag()
self._conn.patch(self.path, data={'SecureBootEnable': enabled},
etag=etag)