Merge "TPM: bump service version to enable live migration"
This commit is contained in:
@@ -7,6 +7,11 @@ Emulated Trusted Platform Module (vTPM)
|
|||||||
Starting in the 22.0.0 (Victoria) release, Nova supports adding an emulated
|
Starting in the 22.0.0 (Victoria) release, Nova supports adding an emulated
|
||||||
virtual `Trusted Platform Module`__ (vTPM) to guests.
|
virtual `Trusted Platform Module`__ (vTPM) to guests.
|
||||||
|
|
||||||
|
.. versionadded:: 33.0.0 (2026.1 Gazpacho)
|
||||||
|
|
||||||
|
Starting in the 33.0.0 (2026.1 Gazpacho) release, Nova supports live migration
|
||||||
|
of guests with emulated vTPM for the ``host`` TPM secret security mode.
|
||||||
|
|
||||||
.. __: https://en.wikipedia.org/wiki/Trusted_Platform_Module
|
.. __: https://en.wikipedia.org/wiki/Trusted_Platform_Module
|
||||||
|
|
||||||
|
|
||||||
@@ -27,6 +32,11 @@ feature:
|
|||||||
* Set the :oslo.config:option:`libvirt.swtpm_enabled` config option to
|
* Set the :oslo.config:option:`libvirt.swtpm_enabled` config option to
|
||||||
``True``. This will enable support for both TPM version 1.2 and 2.0.
|
``True``. This will enable support for both TPM version 1.2 and 2.0.
|
||||||
|
|
||||||
|
* Optionally set the :oslo.config:option:`libvirt.supported_tpm_secret_security`
|
||||||
|
config option to configure which security modes to enable. The default is all
|
||||||
|
modes enabled: ``user`` and ``host``. See the next section for more details
|
||||||
|
about TPM secret security modes.
|
||||||
|
|
||||||
With the above requirements satisfied, verify vTPM support by inspecting the
|
With the above requirements satisfied, verify vTPM support by inspecting the
|
||||||
traits on the compute node's resource provider:
|
traits on the compute node's resource provider:
|
||||||
|
|
||||||
@@ -34,8 +44,12 @@ traits on the compute node's resource provider:
|
|||||||
|
|
||||||
$ COMPUTE_UUID=$(openstack resource provider list --name $HOST -f value -c uuid)
|
$ COMPUTE_UUID=$(openstack resource provider list --name $HOST -f value -c uuid)
|
||||||
$ openstack resource provider trait list $COMPUTE_UUID | grep SECURITY_TPM
|
$ openstack resource provider trait list $COMPUTE_UUID | grep SECURITY_TPM
|
||||||
| COMPUTE_SECURITY_TPM_1_2 |
|
| COMPUTE_SECURITY_TPM_1_2 |
|
||||||
| COMPUTE_SECURITY_TPM_2_0 |
|
| COMPUTE_SECURITY_TPM_2_0 |
|
||||||
|
| COMPUTE_SECURITY_TPM_CRB |
|
||||||
|
| COMPUTE_SECURITY_TPM_TIS |
|
||||||
|
| COMPUTE_SECURITY_TPM_SECRET_SECURITY_USER |
|
||||||
|
| COMPUTE_SECURITY_TPM_SECRET_SECURITY_HOST |
|
||||||
|
|
||||||
.. __: https://docs.openstack.org/api-guide/key-manager/
|
.. __: https://docs.openstack.org/api-guide/key-manager/
|
||||||
.. __: https://docs.openstack.org/barbican/latest/
|
.. __: https://docs.openstack.org/barbican/latest/
|
||||||
@@ -43,6 +57,55 @@ traits on the compute node's resource provider:
|
|||||||
.. __: https://github.com/stefanberger/libtpms/
|
.. __: https://github.com/stefanberger/libtpms/
|
||||||
|
|
||||||
|
|
||||||
|
Security
|
||||||
|
--------
|
||||||
|
|
||||||
|
With a hardware TPM, the root of trust is a secret known only to the TPM user.
|
||||||
|
In contrast, an emulated TPM comprises a file on disk which the libvirt daemon
|
||||||
|
must be able to present to the guest.
|
||||||
|
|
||||||
|
At rest, this file is encrypted using a passphrase stored in a key manager
|
||||||
|
service as a secret.
|
||||||
|
|
||||||
|
Nova supports a few different security modes that will control secret ownership
|
||||||
|
and visibility to the libvirt API. The passphrase is retrieved and used by
|
||||||
|
libvirt to unlock the emulated TPM data any time the server is booted.
|
||||||
|
|
||||||
|
.. list-table::
|
||||||
|
:header-rows: 1
|
||||||
|
:widths: 20 80
|
||||||
|
|
||||||
|
* - Mode
|
||||||
|
- Description
|
||||||
|
* - ``user``
|
||||||
|
- The passphrase in the key manager is associated with the credentials of
|
||||||
|
the owner of the server (the user who initially created it). The libvirt
|
||||||
|
secret is both ``private`` and ``ephemeral``. A server with this
|
||||||
|
security mode cannot be live migrated. This is the default mode.
|
||||||
|
Existing servers that were created before 33.0.0 (2026.1 Gazpacho) will
|
||||||
|
also have this mode.
|
||||||
|
* - ``host``
|
||||||
|
- The passphrase in the key manager is associated with the credentials of
|
||||||
|
the owner of the server (the user who initially created it). The libvirt
|
||||||
|
secret is not ``private`` and not ``ephemeral``, which means it can be
|
||||||
|
retrieved via the libvirt API or ``virsh`` and it exists on disk. A
|
||||||
|
server with this security mode can be live migrated, including by users
|
||||||
|
other than the owner of the server, such as admin, if API policy allows.
|
||||||
|
To transport the TPM secret to the destination host during a live
|
||||||
|
migration, the libvirt secret is sent over RPC.
|
||||||
|
|
||||||
|
Although the above ``user`` mechanism uses a libvirt secret__ that is both
|
||||||
|
``private`` (can't be displayed via the libvirt API or ``virsh``) and
|
||||||
|
``ephemeral`` (exists only in memory, never on disk), it is theoretically
|
||||||
|
possible for a sufficiently privileged user to retrieve the secret and/or vTPM
|
||||||
|
data from memory.
|
||||||
|
|
||||||
|
A full analysis and discussion of security issues related to emulated TPM is
|
||||||
|
beyond the scope of this document.
|
||||||
|
|
||||||
|
.. __: https://libvirt.org/formatsecret.html#SecretAttributes
|
||||||
|
|
||||||
|
|
||||||
Configuring a flavor or image
|
Configuring a flavor or image
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
@@ -65,6 +128,10 @@ model is only supported with version 2.0.
|
|||||||
- ``hw_tpm_model``
|
- ``hw_tpm_model``
|
||||||
- Specify the TPM model, ``tpm-tis`` (the default) or ``tpm-crb`` (only
|
- Specify the TPM model, ``tpm-tis`` (the default) or ``tpm-crb`` (only
|
||||||
valid with version ``2.0``.
|
valid with version ``2.0``.
|
||||||
|
* - ``hw:tpm_secret_security``
|
||||||
|
- \-
|
||||||
|
- Specify the TPM secret security mode, ``user`` (the default) or
|
||||||
|
``host``.
|
||||||
|
|
||||||
For example, to configure a flavor to use the TPM 2.0 with the CRB model:
|
For example, to configure a flavor to use the TPM 2.0 with the CRB model:
|
||||||
|
|
||||||
@@ -81,38 +148,55 @@ Upon successful boot, the server should see a TPM device such as ``/dev/tpm0``
|
|||||||
which can be used in the same manner as a hardware TPM.
|
which can be used in the same manner as a hardware TPM.
|
||||||
|
|
||||||
|
|
||||||
|
Legacy servers and live migration
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
A legacy server can be converted to a TPM secret security mode capable of live
|
||||||
|
migration via a resize to a flavor that has the ``hw:tpm_secret_security``
|
||||||
|
extra spec set to ``host``.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ openstack flavor set $FLAVOR \
|
||||||
|
--property hw:tpm_version=2.0 \
|
||||||
|
--property hw:tpm_model=tpm-crb \
|
||||||
|
--property hw:tpm_secret_security=host
|
||||||
|
|
||||||
|
$ openstack server resize --flavor $FLAVOR $SERVER
|
||||||
|
|
||||||
|
$ openstack server resize confirm $SERVER
|
||||||
|
|
||||||
|
|
||||||
Limitations
|
Limitations
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
* Only server operations performed by the server owner are supported, as the
|
* Rebuild, evacuate, shelve, and rescue of servers with vTPMs is not currently
|
||||||
user's credentials are required to unlock the virtual device files on the
|
supported.
|
||||||
host. Thus the admin may need to decide whether to grant the user additional
|
|
||||||
policy roles; if not, those operations are effectively disabled.
|
|
||||||
|
|
||||||
* Live migration, evacuation, shelving and rescuing of servers with vTPMs is
|
* Other limitations will depend on the TPM secret security mode of the server.
|
||||||
not currently supported.
|
|
||||||
|
|
||||||
|
.. list-table::
|
||||||
|
:header-rows: 1
|
||||||
|
:widths: 20 80
|
||||||
|
|
||||||
Security
|
* - Mode
|
||||||
--------
|
- Description
|
||||||
|
* - ``user``
|
||||||
With a hardware TPM, the root of trust is a secret known only to the TPM user.
|
- Only server operations performed by the server owner are supported, as
|
||||||
In contrast, an emulated TPM comprises a file on disk which the libvirt daemon
|
the user's credentials are required to unlock the virtual device files
|
||||||
must be able to present to the guest. At rest, this file is encrypted using a
|
on the host in this mode. Thus the admin may need to decide whether to
|
||||||
passphrase stored in a key manager service. The passphrase in the key manager
|
grant the user additional policy roles or key manager service ACLs; if
|
||||||
is associated with the credentials of the owner of the server (the user who
|
not, those operations are effectively disabled. Live migration is not
|
||||||
initially created it). The passphrase is retrieved and used by libvirt to
|
supported in this mode.
|
||||||
unlock the emulated TPM data any time the server is booted.
|
* - ``host``
|
||||||
|
- Certain server operations performed by users other than the server
|
||||||
Although the above mechanism uses a libvirt secret__ that is both ``private``
|
owner are supported. Hard reboot, start from stopped, and live migration
|
||||||
(can't be displayed via the libvirt API or ``virsh``) and ``ephemeral`` (exists
|
are supported if API policy allows, without need of key manager service
|
||||||
only in memory, never on disk), it is theoretically possible for a sufficiently
|
ACLs. This is because nova-compute can read the locally stored Libvirt
|
||||||
privileged user to retrieve the secret and/or vTPM data from memory.
|
secret from the server's compute host in this mode and the server
|
||||||
|
owner's credentials are not required.
|
||||||
A full analysis and discussion of security issues related to emulated TPM is
|
|
||||||
beyond the scope of this document.
|
|
||||||
|
|
||||||
.. __: https://libvirt.org/formatsecret.html#SecretAttributes
|
|
||||||
|
|
||||||
|
|
||||||
References
|
References
|
||||||
|
|||||||
+2
-3
@@ -129,7 +129,7 @@ SUPPORT_SHARES = 67
|
|||||||
MIN_COMPUTE_SOUND_MODEL_TRAITS = 69
|
MIN_COMPUTE_SOUND_MODEL_TRAITS = 69
|
||||||
MIN_COMPUTE_USB_MODEL_TRAITS = 70
|
MIN_COMPUTE_USB_MODEL_TRAITS = 70
|
||||||
|
|
||||||
MIN_COMPUTE_VTPM_LIVE_MIGRATION = None
|
MIN_COMPUTE_VTPM_LIVE_MIGRATION = 72
|
||||||
|
|
||||||
# FIXME(danms): Keep a global cache of the cells we find the
|
# FIXME(danms): Keep a global cache of the cells we find the
|
||||||
# first time we look. This needs to be refreshed on a timer or
|
# first time we look. This needs to be refreshed on a timer or
|
||||||
@@ -290,8 +290,7 @@ def reject_legacy_vtpm_live_migration(function):
|
|||||||
with nova_context.target_cell(context, im.cell_mapping) as cctxt:
|
with nova_context.target_cell(context, im.cell_mapping) as cctxt:
|
||||||
min_ver = objects.service.Service.get_minimum_version(
|
min_ver = objects.service.Service.get_minimum_version(
|
||||||
cctxt, 'nova-compute')
|
cctxt, 'nova-compute')
|
||||||
if (MIN_COMPUTE_VTPM_LIVE_MIGRATION is None or
|
if min_ver < MIN_COMPUTE_VTPM_LIVE_MIGRATION:
|
||||||
min_ver < MIN_COMPUTE_VTPM_LIVE_MIGRATION):
|
|
||||||
raise exception.VTPMOldCompute()
|
raise exception.VTPMOldCompute()
|
||||||
return function(self, context, instance, *args, **kwargs)
|
return function(self, context, instance, *args, **kwargs)
|
||||||
return inner
|
return inner
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ __all__ = [
|
|||||||
|
|
||||||
|
|
||||||
# NOTE(danms): This is the global service version counter
|
# NOTE(danms): This is the global service version counter
|
||||||
SERVICE_VERSION = 71
|
SERVICE_VERSION = 72
|
||||||
|
|
||||||
|
|
||||||
# NOTE(danms): This is our SERVICE_VERSION history. The idea is that any
|
# NOTE(danms): This is our SERVICE_VERSION history. The idea is that any
|
||||||
@@ -252,6 +252,9 @@ SERVICE_VERSION_HISTORY = (
|
|||||||
# Version 71: Compute RPC v6.5:
|
# Version 71: Compute RPC v6.5:
|
||||||
# Add 2nd RPC server for compute service
|
# Add 2nd RPC server for compute service
|
||||||
{'compute_rpc': '6.5'},
|
{'compute_rpc': '6.5'},
|
||||||
|
# Version 72: Compute RPC v6.5:
|
||||||
|
# Add support for vTPM live migration
|
||||||
|
{'compute_rpc': '6.5'},
|
||||||
)
|
)
|
||||||
|
|
||||||
# This is the version after which we can rely on having a persistent
|
# This is the version after which we can rely on having a persistent
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
features:
|
||||||
|
- |
|
||||||
|
The libvirt driver now supports live migration of servers with virtual
|
||||||
|
emulated TPM (vTPM) when the ``hw:tpm_secret_security`` flavor extra spec
|
||||||
|
is set to ``host``. Operators must create flavors which set
|
||||||
|
``hw:tpm_secret_security`` in order to enable servers to select a
|
||||||
|
particular TPM secret security mode. Pre-existing servers can opt-in to the
|
||||||
|
``host`` TPM secret security mode by resizing to a flavor which has set
|
||||||
|
``hw:tpm_secret_security`` to ``host``. Operators may choose which TPM
|
||||||
|
security modes they want to support by setting the
|
||||||
|
``[libvirt]supported_tpm_secret_security`` configuration option on compute
|
||||||
|
hosts. See the documentation for details:
|
||||||
|
https://docs.openstack.org/nova/latest/admin/emulated-tpm.html
|
||||||
Reference in New Issue
Block a user