[PATCH v4 0/7] Add TLS-PSK support for migration
QEMU provides the capability to encrypt the migration data stream using two transport layer security (TLS) authentication schemes: X.509 certificates and pre-shared keys (PSK). Currently, Libvirt only supports the X.509-based TLS authentication scheme. In TLS X.509 certificates, a set of live migrations utilize a fixed set of static certificates for encrypted migration. In this authentication scheme, users require to deploy a certificate authority and monitor the certificate expiration window. In case certificates are compromised all the future live migrations are vulnerable. To resolve this, this patch series introduce the support for pre-shared key-based authentication scheme. This mechanism relies on symmetric pre-shared keys (a secret key that is known to both sender and receiver prior to secure communication) for providing secure transfer of data. Libvirt solely manages the lifecycle of the ephemeral pre-shared keys, including, generation, persistent storage, and cleanup. Libvirt generates the key on the source machine, then transfers it to the destination machine using the migration cookie. To allow users to configure the size of the key, Libvirt provides the migrate_tls_psk_length configuration parameter in qemu.conf. We enable the PSK-based TLS authentication scheme if both source and destination supports the tls-creds-psk object regardless of the value of VIR_MIGRATE_TLS flag. Else, we use the X.509-based TLS authentication scheme if the VIR_MIGRATE_TLS flag is set. v4: 1. Enable TLS-PSK if source and destination supports it regardless of the VIR_MIGRATE_TLS flag. 2. If either source or destination does not support TLS-PSK and the VIR_MIGRATE_TLS flag is set then fallback to TLS X509 v3: 1. Destination host decides which TLS authentication scheme to use. 2. The directory of the key file is set to <tls_psk_state_dir>/$ID-$VMNAME. 3. Use the same alias for both tls-creds-x509 and tls-creds-psk objects. 4. Validate the length of the pre-shared key. 5. Unit test to validate the pre-shared key in the migration cookie. v2: 1. Libvirt manages the lifecycle of pre-shared keys. 2. Transfer of keys to the destination via the migration cookie 3. Remove the VIR_MIGRATE_TLS_PSK flag instead rely on VIR_MIGRATE_TLS and availability of ca-cert.pem on source. 4. Drop VIR_MIGRATE_PARAM_TLS_PSK_DIRECTORY, Libvirt solely manages the pre-shared keys. Abhisek Panda (7): conf: Add a configuration param for TLS-PSK qemu: Manage a pre-shared key's lifecycle qemu: Add support to build the tls-creds-psk object qemu: rename tls-creds-x509 obj related functions qemu: Manage tls-creds-psk object lifecycle qemu: Set up the migrate TLS-PSK objects tests: Add testing of pre-shared key lifecycle include/libvirt/libvirt-domain.h | 10 +- src/qemu/libvirtd_qemu.aug | 1 + src/qemu/qemu.conf.in | 8 + src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 26 +++ src/qemu/qemu_command.h | 7 + src/qemu/qemu_conf.c | 22 +++ src/qemu/qemu_conf.h | 2 + src/qemu/qemu_domain.c | 1 + src/qemu/qemu_domain.h | 1 + src/qemu/qemu_driver.c | 6 + src/qemu/qemu_hotplug.c | 40 ++--- src/qemu/qemu_hotplug.h | 24 +-- src/qemu/qemu_migration.c | 170 +++++++++++++++--- src/qemu/qemu_migration.h | 3 + src/qemu/qemu_migration_cookie.c | 79 +++++++- src/qemu/qemu_migration_cookie.h | 5 + src/qemu/qemu_migration_params.c | 98 ++++++++-- src/qemu/qemu_migration_params.h | 22 ++- src/qemu/qemu_process.c | 3 + src/qemu/test_libvirtd_qemu.aug.in | 1 + .../caps_10.0.0_aarch64.xml | 1 + .../caps_10.0.0_ppc64.xml | 1 + .../caps_10.0.0_s390x.xml | 1 + .../caps_10.0.0_x86_64+amdsev.xml | 1 + .../caps_10.0.0_x86_64.xml | 1 + .../caps_10.1.0_s390x.xml | 1 + .../caps_10.1.0_x86_64+inteltdx.xml | 1 + .../caps_10.1.0_x86_64.xml | 1 + .../caps_10.2.0_aarch64.xml | 1 + .../caps_10.2.0_x86_64+mshv.xml | 1 + .../caps_10.2.0_x86_64.xml | 1 + .../caps_11.0.0_aarch64.xml | 1 + .../caps_11.0.0_s390x.xml | 1 + .../caps_11.0.0_x86_64+sgx.xml | 1 + .../caps_11.0.0_x86_64.xml | 1 + .../caps_11.1.0_aarch64.xml | 1 + .../caps_11.1.0_s390x.xml | 1 + .../caps_11.1.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml | 1 + .../caps_7.2.0_x86_64+hvf.xml | 1 + .../caps_7.2.0_x86_64.xml | 1 + .../caps_8.0.0_x86_64.xml | 1 + .../qemucapabilitiesdata/caps_8.1.0_s390x.xml | 1 + .../caps_8.1.0_x86_64.xml | 1 + .../caps_8.2.0_aarch64.xml | 1 + .../caps_8.2.0_armv7l.xml | 1 + .../caps_8.2.0_loongarch64.xml | 1 + .../qemucapabilitiesdata/caps_8.2.0_s390x.xml | 1 + .../caps_8.2.0_x86_64.xml | 1 + .../qemucapabilitiesdata/caps_9.0.0_sparc.xml | 1 + .../caps_9.0.0_x86_64.xml | 1 + .../caps_9.1.0_riscv64.xml | 1 + .../qemucapabilitiesdata/caps_9.1.0_s390x.xml | 1 + .../caps_9.1.0_x86_64.xml | 1 + .../caps_9.2.0_aarch64+hvf.xml | 1 + .../qemucapabilitiesdata/caps_9.2.0_s390x.xml | 1 + .../caps_9.2.0_x86_64+amdsev.xml | 1 + .../caps_9.2.0_x86_64.xml | 1 + tests/qemumigrationcookiexmltest.c | 135 +++++++++++++- tests/testutilsqemu.c | 12 ++ 62 files changed, 632 insertions(+), 85 deletions(-) -- 2.43.7
For encrypted migration of VMs, QEMU provides the TLS-PSK authentication apart from TLS certificates. This mechanism relies on pre-shared keys (a secret key that is known to both sender and receiver prior to secure communication) for providing secure transfer of data. Libvirt handles the lifecycle of pre-shared keys, managing their generation, persistent storage, and cleanup. Add the "migrate_tls_psk_length" configuration attribute to qemu.conf to allow users to define the size of the pre-shared key. Signed-off-by: Abhisek Panda <abhisek.panda1@nutanix.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/libvirtd_qemu.aug | 1 + src/qemu/qemu.conf.in | 8 ++++++++ src/qemu/qemu_conf.c | 18 ++++++++++++++++++ src/qemu/qemu_conf.h | 1 + src/qemu/test_libvirtd_qemu.aug.in | 1 + 5 files changed, 29 insertions(+) diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug index dbcbbb04c0..fc61177ea0 100644 --- a/src/qemu/libvirtd_qemu.aug +++ b/src/qemu/libvirtd_qemu.aug @@ -71,6 +71,7 @@ module Libvirtd_qemu = | str_entry "migrate_tls_x509_secret_uuid" | str_entry "migrate_tls_priority" | bool_entry "migrate_tls_force" + | int_entry "migrate_tls_psk_length" let backup_entry = str_entry "backup_tls_x509_cert_dir" | bool_entry "backup_tls_x509_verify" diff --git a/src/qemu/qemu.conf.in b/src/qemu/qemu.conf.in index de14db6cde..4fdd655881 100644 --- a/src/qemu/qemu.conf.in +++ b/src/qemu/qemu.conf.in @@ -437,6 +437,14 @@ #migrate_tls_force = 0 +# The TLS-PSK authentication relies on pre-shared keys for providing secure transfer of data. +# When TLS-PSK is enabled for the migration operation, Libvirt manages the lifecycle of the +# pre-shared key files. For the key generation process, users can specify the pre-shared +# key size in bytes. The default value is set to 32 bytes. +# +#migrate_tls_psk_length = 32 + + # In order to override the default TLS certificate location for backup NBD # server certificates, supply a valid path to the certificate directory. If the # provided path does not exist, libvirtd will fail to start. If the path is diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 6d67939b6e..cca7776b80 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -77,6 +77,9 @@ VIR_LOG_INIT("qemu.qemu_conf"); #define QEMU_BACKUP_PORT_MIN 10809 #define QEMU_BACKUP_PORT_MAX 10872 +#define QEMU_MIGRATE_TLS_PSK_LENGTH 32 +#define QEMU_MIGRATE_TLS_PSK_LENGTH_MAX 512 + VIR_ENUM_IMPL(virQEMUSchedCore, QEMU_SCHED_CORE_LAST, "none", @@ -616,6 +619,17 @@ virQEMUDriverConfigLoadSpecificTLSEntry(virQEMUDriverConfig *cfg, #undef GET_CONFIG_TLS_CERTINFO_COMMON #undef GET_CONFIG_TLS_CERTINFO_SERVER + + if (virConfGetValueUInt(conf, "migrate_tls_psk_length", &cfg->migrateTLSPSKLength) < 0) + return -1; + + if (cfg->migrateTLSPSKLength > QEMU_MIGRATE_TLS_PSK_LENGTH_MAX) { + virReportError(VIR_ERR_CONF_SYNTAX, + _("migrate_tls_psk_length must not be greater than %1$d"), + QEMU_MIGRATE_TLS_PSK_LENGTH_MAX); + return -1; + } + return 0; } @@ -1596,6 +1610,10 @@ virQEMUDriverConfigSetDefaults(virQEMUDriverConfig *cfg) #undef SET_TLS_VERIFY_DEFAULT + if (cfg->migrateTLSPSKLength == 0) { + cfg->migrateTLSPSKLength = QEMU_MIGRATE_TLS_PSK_LENGTH; + } + return 0; } diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index 9faf6db206..b700829342 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -170,6 +170,7 @@ struct _virQEMUDriverConfig { char *migrateTLSx509secretUUID; char *migrateTLSpriority; bool migrateTLSForce; + unsigned int migrateTLSPSKLength; char *backupTLSx509certdir; bool backupTLSx509verify; diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in index c97d8d7081..9ba39815a6 100644 --- a/src/qemu/test_libvirtd_qemu.aug.in +++ b/src/qemu/test_libvirtd_qemu.aug.in @@ -45,6 +45,7 @@ module Test_libvirtd_qemu = { "migrate_tls_x509_secret_uuid" = "00000000-0000-0000-0000-000000000000" } { "migrate_tls_priority" = "@SYSTEM" } { "migrate_tls_force" = "0" } +{ "migrate_tls_psk_length" = "32" } { "backup_tls_x509_cert_dir" = "/etc/pki/libvirt-backup" } { "backup_tls_x509_verify" = "1" } { "backup_tls_x509_secret_uuid" = "00000000-0000-0000-0000-000000000000" } -- 2.43.7
Libvirt by default attempt to use the TLS-PSK-enabled VM migration, if the both source and destination support the tls-creds-psk object. The source host adds the pre-shared key in the migration cookie if the source supports the tls-creds-psk object. Upon parsing the migration cookie, the destination host checks for the same capability and informs the source host whether to use TLS X.509 or TLS PSK during VM migration via the migration cookie. For a migration session, Libvirt generates a random key of the specified length, and then stores the content, "qemu:<random key>", at <tls_psk_state_dir>/$ID-$VMNAME/keys.psk on the source host. This is because QEMU's tls-creds-psk object does not accept a raw key string as a parameter, it only accepts a dir argument pointing to a directory from which it can read the key file. Subsequently, it sends the key to destination by embedding it within the migration cookie. The destination's Libvirt extracts the key from the migration cookie. Upon migration completion or any failure, both source and destination Libvirt must delete the directory containing the session's keys.psk. Signed-off-by: Abhisek Panda <abhisek.panda1@nutanix.com> --- src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_conf.c | 4 + src/qemu/qemu_conf.h | 1 + src/qemu/qemu_domain.c | 1 + src/qemu/qemu_domain.h | 1 + src/qemu/qemu_driver.c | 6 ++ src/qemu/qemu_migration.c | 98 +++++++++++++++++++ src/qemu/qemu_migration.h | 3 + src/qemu/qemu_migration_cookie.c | 79 ++++++++++++++- src/qemu/qemu_migration_cookie.h | 5 + src/qemu/qemu_process.c | 3 + .../caps_10.0.0_aarch64.xml | 1 + .../caps_10.0.0_ppc64.xml | 1 + .../caps_10.0.0_s390x.xml | 1 + .../caps_10.0.0_x86_64+amdsev.xml | 1 + .../caps_10.0.0_x86_64.xml | 1 + .../caps_10.1.0_s390x.xml | 1 + .../caps_10.1.0_x86_64+inteltdx.xml | 1 + .../caps_10.1.0_x86_64.xml | 1 + .../caps_10.2.0_aarch64.xml | 1 + .../caps_10.2.0_x86_64+mshv.xml | 1 + .../caps_10.2.0_x86_64.xml | 1 + .../caps_11.0.0_aarch64.xml | 1 + .../caps_11.0.0_s390x.xml | 1 + .../caps_11.0.0_x86_64+sgx.xml | 1 + .../caps_11.0.0_x86_64.xml | 1 + .../caps_11.1.0_aarch64.xml | 1 + .../caps_11.1.0_s390x.xml | 1 + .../caps_11.1.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml | 1 + .../caps_7.2.0_x86_64+hvf.xml | 1 + .../caps_7.2.0_x86_64.xml | 1 + .../caps_8.0.0_x86_64.xml | 1 + .../qemucapabilitiesdata/caps_8.1.0_s390x.xml | 1 + .../caps_8.1.0_x86_64.xml | 1 + .../caps_8.2.0_aarch64.xml | 1 + .../caps_8.2.0_armv7l.xml | 1 + .../caps_8.2.0_loongarch64.xml | 1 + .../qemucapabilitiesdata/caps_8.2.0_s390x.xml | 1 + .../caps_8.2.0_x86_64.xml | 1 + .../qemucapabilitiesdata/caps_9.0.0_sparc.xml | 1 + .../caps_9.0.0_x86_64.xml | 1 + .../caps_9.1.0_riscv64.xml | 1 + .../qemucapabilitiesdata/caps_9.1.0_s390x.xml | 1 + .../caps_9.1.0_x86_64.xml | 1 + .../caps_9.2.0_aarch64+hvf.xml | 1 + .../qemucapabilitiesdata/caps_9.2.0_s390x.xml | 1 + .../caps_9.2.0_x86_64+amdsev.xml | 1 + .../caps_9.2.0_x86_64.xml | 1 + tests/qemumigrationcookiexmltest.c | 12 ++- 51 files changed, 249 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index bc2b0412dc..3db4710dee 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -776,6 +776,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "arm-smmuv3.cmdqv", /* QEMU_CAPS_ARM_SMMUV3_CMDQV */ "iothread.poll-weight", /* QEMU_CAPS_IOTHREAD_POLL_WEIGHT */ "win-dmp.guest-aware", /* QEMU_CAPS_WIN_DMP_GUEST_AWARE */ + "tls-creds-psk", /* QEMU_CAPS_OBJECT_TLS_CREDS_PSK */ ); @@ -1490,6 +1491,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "uefi-vars-sysbus", QEMU_CAPS_DEVICE_UEFI_VARS }, { "monitor-qmp", QEMU_CAPS_OBJECT_MONITOR_QMP }, { "arm-smmuv3", QEMU_CAPS_DEVICE_ARM_SMMUV3 }, + { "tls-creds-psk", QEMU_CAPS_OBJECT_TLS_CREDS_PSK }, }; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 28303fd8f0..1e432cdc41 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -750,6 +750,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_ARM_SMMUV3_CMDQV, /* arm-smmuv3.cmdqv */ QEMU_CAPS_IOTHREAD_POLL_WEIGHT, /* -object iothread.poll-weight */ QEMU_CAPS_WIN_DMP_GUEST_AWARE, /* 'win-dmp' is offered only to a guest that can use it */ + QEMU_CAPS_OBJECT_TLS_CREDS_PSK, /* -object tls-creds-psk */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index cca7776b80..f5c5437c89 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -168,6 +168,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged, cfg->cacheDir = g_strdup_printf("%s/cache/qemu", root); cfg->libDir = g_strdup_printf("%s/lib/qemu", root); cfg->swtpmStorageDir = g_strdup_printf("%s/lib/swtpm", root); + cfg->tlsPSKStateDir = g_strdup_printf("%s/run/psk", root); cfg->saveDir = g_strdup_printf("%s/save", cfg->libDir); cfg->snapshotDir = g_strdup_printf("%s/snapshot", cfg->libDir); @@ -187,6 +188,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged, cfg->stateDir = g_strdup_printf("%s/libvirt/qemu", RUNSTATEDIR); cfg->swtpmStateDir = g_strdup_printf("%s/swtpm", cfg->stateDir); cfg->channelTargetDir = g_strdup_printf("%s/channel", cfg->stateDir); + cfg->tlsPSKStateDir = g_strdup_printf("%s/psk", cfg->stateDir); cfg->cacheDir = g_strdup_printf("%s/cache/libvirt/qemu", LOCALSTATEDIR); @@ -214,6 +216,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged, cfg->stateDir = g_strdup_printf("%s/qemu/run", rundir); cfg->swtpmStateDir = g_strdup_printf("%s/swtpm", cfg->stateDir); cfg->channelTargetDir = g_strdup_printf("%s/channel", cfg->stateDir); + cfg->tlsPSKStateDir = g_strdup_printf("%s/psk", cfg->stateDir); cfg->configBaseDir = virGetUserConfigDirectory(); @@ -375,6 +378,7 @@ static void virQEMUDriverConfigDispose(void *obj) g_free(cfg->dbusStateDir); g_free(cfg->rdpStateDir); g_free(cfg->vncStateDir); + g_free(cfg->tlsPSKStateDir); g_free(cfg->libDir); g_free(cfg->cacheDir); diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index b700829342..2db3440514 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -113,6 +113,7 @@ struct _virQEMUDriverConfig { char *dbusStateDir; char *rdpStateDir; char *vncStateDir; + char *tlsPSKStateDir; /* These two directories are ones QEMU processes use (so must match * the QEMU user/group */ char *libDir; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index a4e5f92840..f4d470553d 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1990,6 +1990,7 @@ qemuDomainObjPrivateFree(void *data) virObjectUnref(priv->monConfig); g_free(priv->lockState); g_free(priv->origname); + g_free(priv->migTLSPSK); virChrdevFree(priv->devs); diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 23e99dc68c..053140f7ec 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -139,6 +139,7 @@ struct _qemuDomainObjPrivate { char *origname; int nbdPort; /* Port used for migration with NBD */ unsigned short migrationPort; + char *migTLSPSK; /* Hex-encoded pre-shared key for TLS-PSK-enabled VM migration session */ unsigned short backupNBDPort; int preMigrationState; unsigned long long preMigrationMemlock; /* Original RLIMIT_MEMLOCK in case diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 8498568623..5548d6f7bd 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -664,6 +664,12 @@ qemuStateInitialize(bool privileged, cfg->vncStateDir); goto error; } + if (virDirCreate(cfg->tlsPSKStateDir, 0700, cfg->user, cfg->group, + VIR_DIR_CREATE_ALLOW_EXIST) < 0) { + virReportSystemError(errno, _("Failed to create TLS PSK state dir %1$s"), + cfg->tlsPSKStateDir); + goto error; + } qemu_driver->inhibitor = virInhibitorNew( VIR_INHIBITOR_WHAT_SHUTDOWN, diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 4a43ab83b0..b9971286fd 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -59,6 +59,7 @@ #include "virprocess.h" #include "virdomainsnapshotobjlist.h" #include "virutil.h" +#include "virsecureerase.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -1503,6 +1504,89 @@ qemuMigrationSrcIsAllowedHostdev(const virDomainDef *def) } +void +qemuMigrationDeletePSKDir(virQEMUDriver *driver, virDomainObj *vm) +{ + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + qemuDomainObjPrivate *priv = vm->privateData; + g_autofree char *dir_path = NULL; + g_autofree char *shortName = NULL; + + if (priv->migTLSPSK) { + virSecureEraseString(priv->migTLSPSK); + g_clear_pointer(&priv->migTLSPSK, g_free); + } + + if (!(shortName = virDomainDefGetShortName(vm->def))) + return; + + dir_path = g_strdup_printf("%s/%s", cfg->tlsPSKStateDir, shortName); + + if (virFileIsDir(dir_path) && + virFileDeleteTree(dir_path) < 0) + VIR_WARN("Failed to delete the directory %s containing the pre-shared keys for migration of domain %s", + dir_path, vm->def->name); +} + + +static int +qemuPersistTLSPSKHelper(int pskFD, + const char *pskPath, + const void *opaque) +{ + const char *key = opaque; + + if (safewrite(pskFD, "qemu:", 5) < 0 || + safewrite(pskFD, key, strlen(key)) < 0) { + virReportSystemError(errno, + _("Unable to write the pre-shared key to file '%1$s'"), + pskPath); + return -1; + } + + return 0; +} + + +static int +qemuMigrationPersistPSK(virQEMUDriver *driver, virDomainObj *vm, const char *tlsPSK) +{ + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + g_autofree char *dir_path = NULL; + g_autofree char *key_path = NULL; + g_autofree char *shortName = NULL; + + if (!(shortName = virDomainDefGetShortName(vm->def))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get the shortened domain name for domain: %1$s"), + vm->def->name); + return -1; + } + + dir_path = g_strdup_printf("%s/%s", cfg->tlsPSKStateDir, shortName); + key_path = g_strdup_printf("%s/keys.psk", dir_path); + + if (virDirCreate(dir_path, 0700, cfg->user, cfg->group, + VIR_DIR_CREATE_ALLOW_EXIST) < 0) { + virReportSystemError(errno, + _("Could not create the directory %1$s for storing PSKs"), + dir_path); + goto error; + } + + if (virFileRewrite(key_path, S_IRUSR, cfg->user, + cfg->group, qemuPersistTLSPSKHelper, + tlsPSK) < 0) + goto error; + + return 0; + + error: + qemuMigrationDeletePSKDir(driver, vm); + return -1; +} + + static int qemuDomainGetMigrationBlockers(virDomainObj *vm, int asyncJob, @@ -2722,6 +2806,9 @@ qemuMigrationSrcBeginXML(virDomainObj *vm, if (priv->origCPU) cookieFlags |= QEMU_MIGRATION_COOKIE_CPU; + if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_TLS_CREDS_PSK)) + cookieFlags |= QEMU_MIGRATION_COOKIE_TLS_PSK; + if (!(flags & VIR_MIGRATE_OFFLINE)) cookieFlags |= QEMU_MIGRATION_COOKIE_CAPS; @@ -2738,6 +2825,9 @@ qemuMigrationSrcBeginXML(virDomainObj *vm, cookieFlags) < 0) return NULL; + if (mig->tlsPSK && qemuMigrationPersistPSK(driver, vm, mig->tlsPSK) < 0) + return NULL; + if (xmlin) { g_autoptr(virDomainDef) def = NULL; @@ -4232,6 +4322,8 @@ qemuMigrationSrcConfirmPhase(virQEMUDriver *driver, privJob->stats.mig.downtime = privMigJob->stats.mig.downtime; } + qemuMigrationDeletePSKDir(driver, vm); + if (flags & VIR_MIGRATE_OFFLINE) return 0; @@ -5274,6 +5366,7 @@ qemuMigrationSrcRun(virQEMUDriver *driver, error: virErrorPreserveLast(&orig_err); + qemuMigrationDeletePSKDir(driver, vm); if (qemuDomainObjIsActive(vm)) { int reason; @@ -7029,6 +7122,8 @@ qemuMigrationDstFinishActive(virQEMUDriver *driver, QEMU_MIGRATION_COOKIE_STATS) < 0) VIR_WARN("Unable to encode migration cookie"); + qemuMigrationDeletePSKDir(driver, vm); + qemuMigrationDstComplete(driver, vm, inPostCopy, VIR_ASYNC_JOB_MIGRATION_IN, vm->job); @@ -7039,6 +7134,8 @@ qemuMigrationDstFinishActive(virQEMUDriver *driver, * overwrites it. */ virErrorPreserveLast(&orig_err); + qemuMigrationDeletePSKDir(driver, vm); + if (qemuDomainObjIsActive(vm)) { if (doKill) { qemuProcessStop(vm, VIR_DOMAIN_SHUTOFF_FAILED, @@ -7197,6 +7294,7 @@ qemuMigrationProcessUnattended(virQEMUDriver *driver, else qemuMigrationSrcComplete(driver, vm, job); + qemuMigrationDeletePSKDir(driver, vm); qemuMigrationJobFinish(vm); if (!virDomainObjIsActive(vm)) diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h index 7e9410e1f7..ce15f8024b 100644 --- a/src/qemu/qemu_migration.h +++ b/src/qemu/qemu_migration.h @@ -279,3 +279,6 @@ int qemuMigrationAnyRefreshStatus(virDomainObj *vm, virDomainAsyncJob asyncJob, virDomainJobStatus *status); + +void +qemuMigrationDeletePSKDir(virQEMUDriver *driver, virDomainObj *vm); diff --git a/src/qemu/qemu_migration_cookie.c b/src/qemu/qemu_migration_cookie.c index 7311a8294b..0cf1ab9590 100644 --- a/src/qemu/qemu_migration_cookie.c +++ b/src/qemu/qemu_migration_cookie.c @@ -20,6 +20,7 @@ #include <gnutls/gnutls.h> #include <gnutls/x509.h> +#include <inttypes.h> #include "locking/domain_lock.h" #include "virerror.h" @@ -27,6 +28,7 @@ #include "virnetdevopenvswitch.h" #include "virstring.h" #include "virutil.h" +#include "virsecureerase.h" #include "qemu_domain.h" #include "qemu_migration_cookie.h" @@ -52,6 +54,7 @@ VIR_ENUM_IMPL(qemuMigrationCookieFlag, "allowReboot", "capabilities", "block-dirty-bitmaps", + "psk", ); @@ -165,6 +168,9 @@ qemuMigrationCookieFree(qemuMigrationCookie *mig) g_free(mig->name); g_free(mig->lockState); g_free(mig->lockDriver); + if (mig->tlsPSK) + virSecureEraseString(mig->tlsPSK); + g_free(mig->tlsPSK); g_clear_pointer(&mig->jobData, virDomainJobDataFree); virCPUDefFree(mig->cpu); qemuMigrationCookieCapsFree(mig->caps); @@ -575,6 +581,51 @@ qemuMigrationCookieAddCaps(qemuMigrationCookie *mig, } +static int +qemuMigrationCookieAddTLSPSK(qemuMigrationCookie *mig, + virQEMUDriver *driver, + virDomainObj *vm) +{ + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + qemuDomainObjPrivate *priv = vm->privateData; + gnutls_datum_t psk_key = {NULL, 0}; + g_autofree char *key = NULL; + size_t key_len; + int ret; + + /* Generate the pre-shared key exactly once for a migration session*/ + if (priv->migTLSPSK) { + mig->tlsPSK = g_strdup(priv->migTLSPSK); + mig->flags |= QEMU_MIGRATION_COOKIE_TLS_PSK; + return 0; + } + + ret = gnutls_key_generate(&psk_key, cfg->migrateTLSPSKLength); + if (ret < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Generation of a pre-shared key failed")); + return -1; + } + key_len = (psk_key.size*2) + 1; + key = g_new0(char, key_len); + + ret = gnutls_hex_encode(&psk_key, key, &key_len); + if (ret < 0) { + gnutls_free(psk_key.data); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Hex encoding of a PSK key failed")); + return -1; + } + + priv->migTLSPSK = g_strdup(key); + mig->tlsPSK = g_steal_pointer(&key); + mig->flags |= QEMU_MIGRATION_COOKIE_TLS_PSK; + + gnutls_free(psk_key.data); + return 0; +} + + static void qemuMigrationCookieGraphicsXMLFormat(virBuffer *buf, qemuMigrationCookieGraphics *grap) @@ -890,6 +941,9 @@ qemuMigrationCookieXMLFormat(virQEMUDriver *driver, if (mig->flags & QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS) qemuMigrationCookieBlockDirtyBitmapsFormat(buf, mig->blockDirtyBitmaps); + if ((mig->flags & QEMU_MIGRATION_COOKIE_TLS_PSK) && mig->tlsPSK) + virBufferAsprintf(buf, "<migration-key>%s</migration-key>\n", mig->tlsPSK); + virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</qemu-migration>\n"); return 0; @@ -1396,6 +1450,12 @@ qemuMigrationCookieXMLParse(qemuMigrationCookie *mig, qemuMigrationCookieBlockDirtyBitmapsParse(ctxt, mig) < 0) return -1; + if (flags & QEMU_MIGRATION_COOKIE_TLS_PSK) { + mig->tlsPSK = virXPathString("string(./migration-key[1])", ctxt); + if (mig->tlsPSK) + mig->flags |= QEMU_MIGRATION_COOKIE_TLS_PSK; + } + return 0; } @@ -1471,14 +1531,29 @@ qemuMigrationCookieFormat(qemuMigrationCookie *mig, qemuMigrationCookieAddCaps(mig, dom, party) < 0) return -1; + if (flags & QEMU_MIGRATION_COOKIE_TLS_PSK) { + switch (party) { + case QEMU_MIGRATION_SOURCE: + if (qemuMigrationCookieAddTLSPSK(mig, driver, dom) < 0) + return -1; + break; + case QEMU_MIGRATION_DESTINATION: + if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_TLS_CREDS_PSK)) { + if (mig->tlsPSK) + virSecureEraseString(mig->tlsPSK); + mig->flags &= ~QEMU_MIGRATION_COOKIE_TLS_PSK; + g_clear_pointer(&mig->tlsPSK, g_free); + } + break; + } + } + if (qemuMigrationCookieXMLFormat(driver, priv->qemuCaps, &buf, mig) < 0) return -1; *cookieoutlen = virBufferUse(&buf) + 1; *cookieout = virBufferContentAndReset(&buf); - VIR_DEBUG("cookielen=%d cookie=%s", *cookieoutlen, *cookieout); - return 0; } diff --git a/src/qemu/qemu_migration_cookie.h b/src/qemu/qemu_migration_cookie.h index 254372234d..fd3b4c5a56 100644 --- a/src/qemu/qemu_migration_cookie.h +++ b/src/qemu/qemu_migration_cookie.h @@ -35,6 +35,7 @@ typedef enum { QEMU_MIGRATION_COOKIE_FLAG_ALLOW_REBOOT, QEMU_MIGRATION_COOKIE_FLAG_CAPS, QEMU_MIGRATION_COOKIE_FLAG_BLOCK_DIRTY_BITMAPS, + QEMU_MIGRATION_COOKIE_FLAG_TLS_PSK, QEMU_MIGRATION_COOKIE_FLAG_LAST } qemuMigrationCookieFlags; @@ -53,6 +54,7 @@ typedef enum { QEMU_MIGRATION_COOKIE_CPU = (1 << QEMU_MIGRATION_COOKIE_FLAG_CPU), QEMU_MIGRATION_COOKIE_CAPS = (1 << QEMU_MIGRATION_COOKIE_FLAG_CAPS), QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS = (1 << QEMU_MIGRATION_COOKIE_FLAG_BLOCK_DIRTY_BITMAPS), + QEMU_MIGRATION_COOKIE_TLS_PSK = (1 << QEMU_MIGRATION_COOKIE_FLAG_TLS_PSK), } qemuMigrationCookieFeatures; typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics; @@ -171,6 +173,9 @@ struct _qemuMigrationCookie { /* If flags & QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS */ GSList *blockDirtyBitmaps; + + /* If flags & QEMU_MIGRATION_COOKIE_TLS_PSK */ + char *tlsPSK; }; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index aaa9046146..15be098c60 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -9413,6 +9413,9 @@ qemuProcessStop(virDomainObj *vm, /* Do this before we delete the tree and remove pidfile. */ qemuProcessKillManagedPRDaemon(vm); + /* PSK files might be left at this point, clean them up */ + qemuMigrationDeletePSKDir(driver, vm); + qemuDomainCleanupRun(driver, vm); qemuExtDevicesStop(driver, vm, !!(flags & VIR_QEMU_PROCESS_STOP_MIGRATED)); diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml index 48629e494d..432517e5bd 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml @@ -166,6 +166,7 @@ <flag name='iommufd'/> <flag name='uefi-vars'/> <flag name='arm-smmuv3'/> + <flag name='tls-creds-psk'/> <version>10000000</version> <microcodeVersion>61700285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_ppc64.xml b/tests/qemucapabilitiesdata/caps_10.0.0_ppc64.xml index 70bf98c404..2d470cbb7c 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_ppc64.xml @@ -170,6 +170,7 @@ <flag name='nvme-ns'/> <flag name='usb-bot'/> <flag name='virtio-iommu.aw-bits'/> + <flag name='tls-creds-psk'/> <version>10000000</version> <microcodeVersion>42900285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml b/tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml index 25d73b6e1d..7cb465678c 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml @@ -137,6 +137,7 @@ <flag name='usb-bot'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='tls-creds-psk'/> <version>10000000</version> <microcodeVersion>39100285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml index 53fd51122c..d35d26ae26 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml @@ -212,6 +212,7 @@ <flag name='iommufd'/> <flag name='uefi-vars'/> <flag name='amd-iommu.xtsup'/> + <flag name='tls-creds-psk'/> <version>10000000</version> <microcodeVersion>43100285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml index ad3fe67638..1d9dd1386d 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml @@ -212,6 +212,7 @@ <flag name='iommufd'/> <flag name='uefi-vars'/> <flag name='amd-iommu.xtsup'/> + <flag name='tls-creds-psk'/> <version>10000000</version> <microcodeVersion>43100285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml b/tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml index 0d46b3b20e..106edc5b18 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_s390x.xml @@ -143,6 +143,7 @@ <flag name='iommufd'/> <flag name='uefi-vars'/> <flag name='blockdev-mirror.target-is-zero'/> + <flag name='tls-creds-psk'/> <version>10001000</version> <microcodeVersion>39100286</microcodeVersion> <package>v10.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml index 242215f7a8..75ba6c9535 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64+inteltdx.xml @@ -196,6 +196,7 @@ <flag name='uefi-vars'/> <flag name='amd-iommu.xtsup'/> <flag name='blockdev-mirror.target-is-zero'/> + <flag name='tls-creds-psk'/> <version>10001000</version> <microcodeVersion>43100286</microcodeVersion> <package>v10.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml index a2faddcced..657de2d18d 100644 --- a/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.1.0_x86_64.xml @@ -218,6 +218,7 @@ <flag name='uefi-vars'/> <flag name='amd-iommu.xtsup'/> <flag name='blockdev-mirror.target-is-zero'/> + <flag name='tls-creds-psk'/> <version>10001000</version> <microcodeVersion>43100286</microcodeVersion> <package>v10.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_10.2.0_aarch64.xml index 3bbba5ddb1..2967d4dbc5 100644 --- a/tests/qemucapabilitiesdata/caps_10.2.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_10.2.0_aarch64.xml @@ -187,6 +187,7 @@ <flag name='blockdev-mirror.target-is-zero'/> <flag name='arm-smmuv3'/> <flag name='arm-smmuv3.smmu_per_bus'/> + <flag name='tls-creds-psk'/> <version>10002000</version> <microcodeVersion>61700287</microcodeVersion> <package>v10.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml index 530c0366ea..1ca902042e 100644 --- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml +++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64+mshv.xml @@ -206,6 +206,7 @@ <flag name='uefi-vars'/> <flag name='amd-iommu.xtsup'/> <flag name='blockdev-mirror.target-is-zero'/> + <flag name='tls-creds-psk'/> <version>10002000</version> <microcodeVersion>43100287</microcodeVersion> <package>v10.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml index b2cd261b99..fe0900ad97 100644 --- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml @@ -219,6 +219,7 @@ <flag name='uefi-vars'/> <flag name='amd-iommu.xtsup'/> <flag name='blockdev-mirror.target-is-zero'/> + <flag name='tls-creds-psk'/> <version>10002000</version> <microcodeVersion>43100287</microcodeVersion> <package>v10.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_11.0.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_11.0.0_aarch64.xml index d77884f401..a6d005b28c 100644 --- a/tests/qemucapabilitiesdata/caps_11.0.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_11.0.0_aarch64.xml @@ -190,6 +190,7 @@ <flag name='arm-smmuv3'/> <flag name='arm-smmuv3.smmu_per_bus'/> <flag name='arm-smmuv3.accel'/> + <flag name='tls-creds-psk'/> <version>11000000</version> <microcodeVersion>61700286</microcodeVersion> <package>v11.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_11.0.0_s390x.xml b/tests/qemucapabilitiesdata/caps_11.0.0_s390x.xml index 07ee859318..3ae8335f5e 100644 --- a/tests/qemucapabilitiesdata/caps_11.0.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_11.0.0_s390x.xml @@ -146,6 +146,7 @@ <flag name='uefi-vars'/> <flag name='query-block-flat'/> <flag name='blockdev-mirror.target-is-zero'/> + <flag name='tls-creds-psk'/> <version>11000000</version> <microcodeVersion>39100286</microcodeVersion> <package>v11.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_11.0.0_x86_64+sgx.xml b/tests/qemucapabilitiesdata/caps_11.0.0_x86_64+sgx.xml index 108f4b0b86..17c7ee8032 100644 --- a/tests/qemucapabilitiesdata/caps_11.0.0_x86_64+sgx.xml +++ b/tests/qemucapabilitiesdata/caps_11.0.0_x86_64+sgx.xml @@ -222,6 +222,7 @@ <flag name='query-block-flat'/> <flag name='amd-iommu.xtsup'/> <flag name='blockdev-mirror.target-is-zero'/> + <flag name='tls-creds-psk'/> <version>11000000</version> <microcodeVersion>43100286</microcodeVersion> <package>v11.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml index 29fdaf20d8..c231e8a44f 100644 --- a/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml @@ -221,6 +221,7 @@ <flag name='query-block-flat'/> <flag name='amd-iommu.xtsup'/> <flag name='blockdev-mirror.target-is-zero'/> + <flag name='tls-creds-psk'/> <version>11000000</version> <microcodeVersion>43100286</microcodeVersion> <package>v11.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.xml index 31d4d2fd26..e2f9ad15bf 100644 --- a/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_11.1.0_aarch64.xml @@ -194,6 +194,7 @@ <flag name='arm-smmuv3.cmdqv'/> <flag name='iothread.poll-weight'/> <flag name='win-dmp.guest-aware'/> + <flag name='tls-creds-psk'/> <version>11001000</version> <microcodeVersion>61700287</microcodeVersion> <package>v11.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_11.1.0_s390x.xml b/tests/qemucapabilitiesdata/caps_11.1.0_s390x.xml index aae4dd0b80..3bc5c3670e 100644 --- a/tests/qemucapabilitiesdata/caps_11.1.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_11.1.0_s390x.xml @@ -149,6 +149,7 @@ <flag name='object-monitor-qmp'/> <flag name='iothread.poll-weight'/> <flag name='win-dmp.guest-aware'/> + <flag name='tls-creds-psk'/> <version>11001000</version> <microcodeVersion>39100287</microcodeVersion> <package>v11.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml index 05e6749a17..81b8c32317 100644 --- a/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml @@ -224,6 +224,7 @@ <flag name='object-monitor-qmp'/> <flag name='iothread.poll-weight'/> <flag name='win-dmp.guest-aware'/> + <flag name='tls-creds-psk'/> <version>11001000</version> <microcodeVersion>43100287</microcodeVersion> <package>v11.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml b/tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml index bf67b3d295..ab8eea349d 100644 --- a/tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml +++ b/tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml @@ -146,6 +146,7 @@ <flag name='nvme'/> <flag name='nvme-ns'/> <flag name='usb-bot'/> + <flag name='tls-creds-psk'/> <version>7002000</version> <microcodeVersion>0</microcodeVersion> <package>qemu-7.2.0-6.fc37</package> diff --git a/tests/qemucapabilitiesdata/caps_7.2.0_x86_64+hvf.xml b/tests/qemucapabilitiesdata/caps_7.2.0_x86_64+hvf.xml index f40d77baa5..1a7ee73a37 100644 --- a/tests/qemucapabilitiesdata/caps_7.2.0_x86_64+hvf.xml +++ b/tests/qemucapabilitiesdata/caps_7.2.0_x86_64+hvf.xml @@ -192,6 +192,7 @@ <flag name='amd-iommu'/> <flag name='usb-bot'/> <flag name='amd-iommu.xtsup'/> + <flag name='tls-creds-psk'/> <version>7002000</version> <microcodeVersion>43100245</microcodeVersion> <package>v7.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_7.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_7.2.0_x86_64.xml index 8d44ed71e0..0f6bdd871b 100644 --- a/tests/qemucapabilitiesdata/caps_7.2.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_7.2.0_x86_64.xml @@ -192,6 +192,7 @@ <flag name='amd-iommu'/> <flag name='usb-bot'/> <flag name='amd-iommu.xtsup'/> + <flag name='tls-creds-psk'/> <version>7002000</version> <microcodeVersion>43100245</microcodeVersion> <package>v7.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_8.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_8.0.0_x86_64.xml index fcbb68e415..906bd87967 100644 --- a/tests/qemucapabilitiesdata/caps_8.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_8.0.0_x86_64.xml @@ -195,6 +195,7 @@ <flag name='nvme-ns'/> <flag name='amd-iommu'/> <flag name='usb-bot'/> + <flag name='tls-creds-psk'/> <version>8000000</version> <microcodeVersion>43100244</microcodeVersion> <package>v8.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_8.1.0_s390x.xml b/tests/qemucapabilitiesdata/caps_8.1.0_s390x.xml index 65f73d1af8..00f6087c30 100644 --- a/tests/qemucapabilitiesdata/caps_8.1.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_8.1.0_s390x.xml @@ -111,6 +111,7 @@ <flag name='usb-mtp'/> <flag name='netdev.user'/> <flag name='usb-bot'/> + <flag name='tls-creds-psk'/> <version>8001000</version> <microcodeVersion>39100245</microcodeVersion> <package>v8.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_8.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_8.1.0_x86_64.xml index c730dd7174..7fac76e8ca 100644 --- a/tests/qemucapabilitiesdata/caps_8.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_8.1.0_x86_64.xml @@ -198,6 +198,7 @@ <flag name='amd-iommu'/> <flag name='usb-bot'/> <flag name='amd-iommu.xtsup'/> + <flag name='tls-creds-psk'/> <version>8001000</version> <microcodeVersion>43100245</microcodeVersion> <package>v8.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_8.2.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_8.2.0_aarch64.xml index 1f0f68092d..2d87411187 100644 --- a/tests/qemucapabilitiesdata/caps_8.2.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_8.2.0_aarch64.xml @@ -161,6 +161,7 @@ <flag name='nvme-ns'/> <flag name='usb-bot'/> <flag name='arm-smmuv3'/> + <flag name='tls-creds-psk'/> <version>8002000</version> <microcodeVersion>61700246</microcodeVersion> <package>v8.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_8.2.0_armv7l.xml b/tests/qemucapabilitiesdata/caps_8.2.0_armv7l.xml index 254ec27545..bdefd4e8ec 100644 --- a/tests/qemucapabilitiesdata/caps_8.2.0_armv7l.xml +++ b/tests/qemucapabilitiesdata/caps_8.2.0_armv7l.xml @@ -168,6 +168,7 @@ <flag name='nvme-ns'/> <flag name='usb-bot'/> <flag name='arm-smmuv3'/> + <flag name='tls-creds-psk'/> <version>8002000</version> <microcodeVersion>0</microcodeVersion> <package>qemu-8.2.0-7.fc39</package> diff --git a/tests/qemucapabilitiesdata/caps_8.2.0_loongarch64.xml b/tests/qemucapabilitiesdata/caps_8.2.0_loongarch64.xml index 95eb2dfa21..aac15bba50 100644 --- a/tests/qemucapabilitiesdata/caps_8.2.0_loongarch64.xml +++ b/tests/qemucapabilitiesdata/caps_8.2.0_loongarch64.xml @@ -150,6 +150,7 @@ <flag name='nvme'/> <flag name='nvme-ns'/> <flag name='usb-bot'/> + <flag name='tls-creds-psk'/> <version>8002000</version> <microcodeVersion>106300246</microcodeVersion> <package>v8.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_8.2.0_s390x.xml b/tests/qemucapabilitiesdata/caps_8.2.0_s390x.xml index 45ab66ec29..d824393638 100644 --- a/tests/qemucapabilitiesdata/caps_8.2.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_8.2.0_s390x.xml @@ -114,6 +114,7 @@ <flag name='nvme'/> <flag name='nvme-ns'/> <flag name='usb-bot'/> + <flag name='tls-creds-psk'/> <version>8002000</version> <microcodeVersion>39100246</microcodeVersion> <package>v8.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_8.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_8.2.0_x86_64.xml index b46505d24b..4b2a6e673a 100644 --- a/tests/qemucapabilitiesdata/caps_8.2.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_8.2.0_x86_64.xml @@ -201,6 +201,7 @@ <flag name='amd-iommu'/> <flag name='usb-bot'/> <flag name='amd-iommu.xtsup'/> + <flag name='tls-creds-psk'/> <version>8002000</version> <microcodeVersion>43100246</microcodeVersion> <package>v8.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.0.0_sparc.xml b/tests/qemucapabilitiesdata/caps_9.0.0_sparc.xml index 44ddfb0f76..4e18fc98aa 100644 --- a/tests/qemucapabilitiesdata/caps_9.0.0_sparc.xml +++ b/tests/qemucapabilitiesdata/caps_9.0.0_sparc.xml @@ -68,6 +68,7 @@ <flag name='display-reload'/> <flag name='netdev.user'/> <flag name='bus-floppy'/> + <flag name='tls-creds-psk'/> <version>9000000</version> <microcodeVersion>0</microcodeVersion> <package>qemu-9.0.0-1.fc40</package> diff --git a/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml index 2f361bd1c8..e9e2903fef 100644 --- a/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml @@ -205,6 +205,7 @@ <flag name='acpi-generic-initiator'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='tls-creds-psk'/> <version>9000000</version> <microcodeVersion>43100245</microcodeVersion> <package>v9.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml b/tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml index f04b2fd302..7c161c34de 100644 --- a/tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml +++ b/tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml @@ -162,6 +162,7 @@ <flag name='usb-bot'/> <flag name='acpi-generic-initiator'/> <flag name='virtio-iommu.aw-bits'/> + <flag name='tls-creds-psk'/> <version>9001000</version> <microcodeVersion>0</microcodeVersion> <package>v9.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml b/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml index 990fe255f6..dfef1fd20e 100644 --- a/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml @@ -127,6 +127,7 @@ <flag name='usb-bot'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='tls-creds-psk'/> <version>9001000</version> <microcodeVersion>39100246</microcodeVersion> <package>v9.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml index 07d7562c84..da4d536fbf 100644 --- a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml @@ -205,6 +205,7 @@ <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> <flag name='amd-iommu.xtsup'/> + <flag name='tls-creds-psk'/> <version>9001000</version> <microcodeVersion>43100246</microcodeVersion> <package>v9.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_aarch64+hvf.xml b/tests/qemucapabilitiesdata/caps_9.2.0_aarch64+hvf.xml index c9e85ff9b3..df8832ab7b 100644 --- a/tests/qemucapabilitiesdata/caps_9.2.0_aarch64+hvf.xml +++ b/tests/qemucapabilitiesdata/caps_9.2.0_aarch64+hvf.xml @@ -136,6 +136,7 @@ <flag name='acpi-generic-initiator'/> <flag name='virtio-iommu.aw-bits'/> <flag name='arm-smmuv3'/> + <flag name='tls-creds-psk'/> <version>9002002</version> <microcodeVersion>61700247</microcodeVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml b/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml index a8f830076e..9474236875 100644 --- a/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml @@ -130,6 +130,7 @@ <flag name='usb-bot'/> <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> + <flag name='tls-creds-psk'/> <version>9002000</version> <microcodeVersion>39100247</microcodeVersion> <package>v9.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml index f67222578d..999d86035b 100644 --- a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml +++ b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml @@ -209,6 +209,7 @@ <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> <flag name='amd-iommu.xtsup'/> + <flag name='tls-creds-psk'/> <version>9002000</version> <microcodeVersion>43100247</microcodeVersion> <package>v9.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml index efd3eeb9c7..1f1b67be74 100644 --- a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml @@ -207,6 +207,7 @@ <flag name='virtio-iommu.aw-bits'/> <flag name='iommufd'/> <flag name='amd-iommu.xtsup'/> + <flag name='tls-creds-psk'/> <version>9002000</version> <microcodeVersion>43100247</microcodeVersion> <package>v9.2.0</package> diff --git a/tests/qemumigrationcookiexmltest.c b/tests/qemumigrationcookiexmltest.c index bc0f68b8c5..41846b8631 100644 --- a/tests/qemumigrationcookiexmltest.c +++ b/tests/qemumigrationcookiexmltest.c @@ -160,8 +160,12 @@ testQemuMigrationCookieParse(const void *opaque) return -1; } - /* set all flags so that formatter attempts to format everything */ - data->cookie->flags = ~0; + /* Set all flags except QEMU_MIGRATION_COOKIE_TLS_PSK so that formatter + * attempts to format everything except the migration-key element. This is + * because the value of the migration-key element is randomly generated every time + * the migration cookie is constructed. + */ + data->cookie->flags = ~QEMU_MIGRATION_COOKIE_TLS_PSK; if (qemuMigrationCookieXMLFormat(&driver, priv->qemuCaps, @@ -225,10 +229,12 @@ testQemuMigrationCookieDom2XML(const char *namesuffix, * - lockstate: internals are NULL in tests, causes crash * - nbd: monitor not present * - dirty bitmaps: monitor not present + * - tls-psk: a new key is generated every time the migration cookie is constructed, so we can't test it */ unsigned int cookiePopulateFlagMask = QEMU_MIGRATION_COOKIE_LOCKSTATE | QEMU_MIGRATION_COOKIE_NBD | - QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS; + QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS | + QEMU_MIGRATION_COOKIE_TLS_PSK; data->cookiePopulateFlags = ~cookiePopulateFlagMask; } -- 2.43.7
Build the tls-creds-psk object with the following params: id, dir, endpoint. Note: Libvirt generates a keys.psk file for each migration session that only contains the pre-shared key for the "qemu" user. Because QEMU defaults to using "qemu" as the username if the username attribute of the tls-creds-psk object is undefined. We intentionally do not set this attribute. Suggested-by: Tejus GK <tejus.gk@nutanix.com> Signed-off-by: Abhisek Panda <abhisek.panda1@nutanix.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_command.c | 26 ++++++++++++++++++++++++++ src/qemu/qemu_command.h | 7 +++++++ 2 files changed, 33 insertions(+) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index a07b915f4d..d065dd7350 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1293,6 +1293,32 @@ qemuBuildTLSx509CommandLine(virCommand *cmd, } +/* qemuBuildTLSPSKBackendProps: + * @tlsPSKPath: path to the TLS-PSK credentials file + * @isListen: boolean listen for client or server setting + * @alias: alias for the TLS-PSK object + * @propsret: json properties to return + * + * Create a backend string for the tls-creds-psk object. + * + * Returns 0 on success, -1 on failure with error set. + */ +int +qemuBuildTLSPSKBackendProps(const char *tlsPSKPath, + bool isListen, + const char *alias, + virJSONValue **propsret) +{ + if (qemuMonitorCreateObjectProps(propsret, "tls-creds-psk", alias, + "s:dir", tlsPSKPath, + "s:endpoint", (isListen ? "server": "client"), + NULL) < 0) + return -1; + + return 0; +} + + static int qemuBuildChardevCommand(virCommand *cmd, const virDomainChrSourceDef *dev, diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index e34172fbff..92ae32d285 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -72,6 +72,13 @@ qemuBuildTLSx509BackendProps(const char *tlspath, const char *secalias, virJSONValue **propsret); +/* Generate the object properties for a tls-creds-psk */ +int +qemuBuildTLSPSKBackendProps(const char *tlsPSKPath, + bool isListen, + const char *alias, + virJSONValue **propsret); + /* Open a UNIX socket for chardev FD passing */ int qemuOpenChrChardevUNIXSocket(const virDomainChrSourceDef *dev); -- 2.43.7
Append 'x509' to the function identifiers managing the tls-creds-x509 objects. This defines the functions' scope and prevents naming conflicts with the introduction of functions related to tls-creds-psk in subsequent commits. Suggested-by: Tejus GK <tejus.gk@nutanix.com> Signed-off-by: Abhisek Panda <abhisek.panda1@nutanix.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_hotplug.c | 40 ++++++++++++++++---------------- src/qemu/qemu_hotplug.h | 24 +++++++++---------- src/qemu/qemu_migration.c | 16 ++++++------- src/qemu/qemu_migration_params.c | 32 ++++++++++++------------- src/qemu/qemu_migration_params.h | 14 +++++------ 5 files changed, 63 insertions(+), 63 deletions(-) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 961885c0e2..5479ab1bce 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1735,10 +1735,10 @@ qemuDomainDelTLSObjects(virDomainObj *vm, int -qemuDomainAddTLSObjects(virDomainObj *vm, - virDomainAsyncJob asyncJob, - virJSONValue **secProps, - virJSONValue **tlsProps) +qemuDomainAddTLSx509Objects(virDomainObj *vm, + virDomainAsyncJob asyncJob, + virJSONValue **secProps, + virJSONValue **tlsProps) { qemuDomainObjPrivate *priv = vm->privateData; virErrorPtr orig_err; @@ -1772,14 +1772,14 @@ qemuDomainAddTLSObjects(virDomainObj *vm, int -qemuDomainGetTLSObjects(qemuDomainSecretInfo *secinfo, - const char *tlsCertdir, - bool tlsListen, - bool tlsVerify, - const char *tlsPriority, - const char *alias, - virJSONValue **tlsProps, - virJSONValue **secProps) +qemuDomainGetTLSx509Objects(qemuDomainSecretInfo *secinfo, + const char *tlsCertdir, + bool tlsListen, + bool tlsVerify, + const char *tlsPriority, + const char *alias, + virJSONValue **tlsProps, + virJSONValue **secProps) { const char *secAlias = NULL; @@ -1830,18 +1830,18 @@ qemuDomainAddChardevTLSObjects(virQEMUDriver *driver, if (!(*tlsAlias = qemuAliasTLSObjFromSrcAlias(charAlias))) return -1; - if (qemuDomainGetTLSObjects(secinfo, - cfg->chardevTLSx509certdir, - dev->data.tcp.listen, - cfg->chardevTLSx509verify, - cfg->chardevTLSpriority, - *tlsAlias, &tlsProps, &secProps) < 0) + if (qemuDomainGetTLSx509Objects(secinfo, + cfg->chardevTLSx509certdir, + dev->data.tcp.listen, + cfg->chardevTLSx509verify, + cfg->chardevTLSpriority, + *tlsAlias, &tlsProps, &secProps) < 0) return -1; dev->data.tcp.tlscreds = true; - if (qemuDomainAddTLSObjects(vm, VIR_ASYNC_JOB_NONE, - &secProps, &tlsProps) < 0) + if (qemuDomainAddTLSx509Objects(vm, VIR_ASYNC_JOB_NONE, + &secProps, &tlsProps) < 0) return -1; return 0; diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h index 60ed0e174c..0c969ab7f0 100644 --- a/src/qemu/qemu_hotplug.h +++ b/src/qemu/qemu_hotplug.h @@ -31,20 +31,20 @@ qemuDomainDelTLSObjects(virDomainObj *vm, const char *tlsAlias); int -qemuDomainAddTLSObjects(virDomainObj *vm, - virDomainAsyncJob asyncJob, - virJSONValue **secProps, - virJSONValue **tlsProps); +qemuDomainAddTLSx509Objects(virDomainObj *vm, + virDomainAsyncJob asyncJob, + virJSONValue **secProps, + virJSONValue **tlsProps); int -qemuDomainGetTLSObjects(qemuDomainSecretInfo *secinfo, - const char *tlsCertdir, - bool tlsListen, - bool tlsVerify, - const char *tlsPriority, - const char *alias, - virJSONValue **tlsProps, - virJSONValue **secProps); +qemuDomainGetTLSx509Objects(qemuDomainSecretInfo *secinfo, + const char *tlsCertdir, + bool tlsListen, + bool tlsVerify, + const char *tlsPriority, + const char *alias, + virJSONValue **tlsProps, + virJSONValue **secProps); int qemuDomainAttachDiskGeneric(virDomainObj *vm, diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index b9971286fd..2fc8af9c15 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -3502,10 +3502,10 @@ qemuMigrationDstPrepareActive(virQEMUDriver *driver, /* Migrations using TLS need to add the "tls-creds-x509" object and * set the migration TLS parameters */ if (flags & VIR_MIGRATE_TLS) { - if (qemuMigrationParamsEnableTLS(driver, vm, true, - VIR_ASYNC_JOB_MIGRATION_IN, - &tlsAlias, NULL, - migParams) < 0) + if (qemuMigrationParamsEnableTLSx509(driver, vm, true, + VIR_ASYNC_JOB_MIGRATION_IN, + &tlsAlias, NULL, + migParams) < 0) goto error; } else { if (qemuMigrationParamsDisableTLS(vm, migParams) < 0) @@ -5161,10 +5161,10 @@ qemuMigrationSrcRun(virQEMUDriver *driver, spec->destType == MIGRATION_DEST_FD) hostname = spec->dest.host.name; - if (qemuMigrationParamsEnableTLS(driver, vm, false, - VIR_ASYNC_JOB_MIGRATION_OUT, - &tlsAlias, hostname, - migParams) < 0) + if (qemuMigrationParamsEnableTLSx509(driver, vm, false, + VIR_ASYNC_JOB_MIGRATION_OUT, + &tlsAlias, hostname, + migParams) < 0) goto error; } else { if (qemuMigrationParamsDisableTLS(vm, migParams) < 0) diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c index dd47516742..d551ab9216 100644 --- a/src/qemu/qemu_migration_params.c +++ b/src/qemu/qemu_migration_params.c @@ -1150,12 +1150,12 @@ qemuMigrationParamsSetString(qemuMigrationParams *migParams, } -/* qemuMigrationParamsEnableTLS +/* qemuMigrationParamsEnableTLSx509 * @driver: pointer to qemu driver * @vm: domain object * @tlsListen: server or client * @asyncJob: Migration job to join - * @tlsAlias: alias to be generated for TLS object + * @tlsAlias: alias to be generated for TLS X.509 object * @hostname: hostname of the migration destination * @migParams: migration parameters to set * @@ -1166,17 +1166,17 @@ qemuMigrationParamsSetString(qemuMigrationParams *migParams, * Returns 0 on success, -1 on failure */ int -qemuMigrationParamsEnableTLS(virQEMUDriver *driver, - virDomainObj *vm, - bool tlsListen, - int asyncJob, - char **tlsAlias, - const char *hostname, - qemuMigrationParams *migParams) +qemuMigrationParamsEnableTLSx509(virQEMUDriver *driver, + virDomainObj *vm, + bool tlsListen, + int asyncJob, + char **tlsAlias, + const char *hostname, + qemuMigrationParams *migParams) { qemuDomainObjPrivate *priv = vm->privateData; qemuDomainJobPrivate *jobPriv = vm->job->privateData; - g_autoptr(virJSONValue) tlsProps = NULL; + g_autoptr(virJSONValue) tlsx509Props = NULL; g_autoptr(virJSONValue) secProps = NULL; g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); const char *secAlias = NULL; @@ -1205,11 +1205,11 @@ qemuMigrationParamsEnableTLS(virQEMUDriver *driver, if (!(*tlsAlias = qemuAliasTLSObjFromSrcAlias(QEMU_MIGRATION_TLS_ALIAS_BASE))) return -1; - if (qemuDomainGetTLSObjects(priv->migSecinfo, - cfg->migrateTLSx509certdir, tlsListen, - cfg->migrateTLSx509verify, - cfg->migrateTLSpriority, - *tlsAlias, &tlsProps, &secProps) < 0) + if (qemuDomainGetTLSx509Objects(priv->migSecinfo, + cfg->migrateTLSx509certdir, tlsListen, + cfg->migrateTLSx509verify, + cfg->migrateTLSpriority, + *tlsAlias, &tlsx509Props, &secProps) < 0) return -1; /* Ensure the domain doesn't already have the TLS objects defined... @@ -1218,7 +1218,7 @@ qemuMigrationParamsEnableTLS(virQEMUDriver *driver, * some other error path between now and perform . */ qemuDomainDelTLSObjects(vm, asyncJob, secAlias, *tlsAlias); - if (qemuDomainAddTLSObjects(vm, asyncJob, &secProps, &tlsProps) < 0) + if (qemuDomainAddTLSx509Objects(vm, asyncJob, &secProps, &tlsx509Props) < 0) return -1; if (qemuMigrationParamsSetString(migParams, diff --git a/src/qemu/qemu_migration_params.h b/src/qemu/qemu_migration_params.h index b7a829b85a..14e20fb71e 100644 --- a/src/qemu/qemu_migration_params.h +++ b/src/qemu/qemu_migration_params.h @@ -115,13 +115,13 @@ qemuMigrationParamsApply(virDomainObj *vm, unsigned int apiFlags); int -qemuMigrationParamsEnableTLS(virQEMUDriver *driver, - virDomainObj *vm, - bool tlsListen, - int asyncJob, - char **tlsAlias, - const char *hostname, - qemuMigrationParams *migParams); +qemuMigrationParamsEnableTLSx509(virQEMUDriver *driver, + virDomainObj *vm, + bool tlsListen, + int asyncJob, + char **tlsAlias, + const char *hostname, + qemuMigrationParams *migParams); int qemuMigrationParamsDisableTLS(virDomainObj *vm, -- 2.43.7
To enable TLS-PSK-based authentication scheme, add support for instantiating the tls-creds-psk object through QEMU monitor. Suggested-by: Tejus GK <tejus.gk@nutanix.com> Signed-off-by: Abhisek Panda <abhisek.panda1@nutanix.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_migration_params.c | 66 ++++++++++++++++++++++++++++++++ src/qemu/qemu_migration_params.h | 8 ++++ 2 files changed, 74 insertions(+) diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c index d551ab9216..678bb5602b 100644 --- a/src/qemu/qemu_migration_params.c +++ b/src/qemu/qemu_migration_params.c @@ -31,6 +31,7 @@ #define LIBVIRT_QEMU_MIGRATION_PARAMSPRIV_H_ALLOW #include "qemu_migration_paramspriv.h" #include "qemu_monitor.h" +#include "qemu_command.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -1237,6 +1238,71 @@ qemuMigrationParamsEnableTLSx509(virQEMUDriver *driver, } +/* qemuMigrationParamsEnableTLSPSK + * @driver: pointer to qemu driver + * @vm: domain object + * @tlsListen: server or client + * @asyncJob: Migration job to join + * @tlsPSKAlias: alias to be generated for TLS-PSK object + * @migParams: migration parameters to set + * + * Create the TLS PSK objects for the migration and set the migParams value. + * + * Returns 0 on success, -1 on failure + */ +int +qemuMigrationParamsEnableTLSPSK(virQEMUDriver *driver, + virDomainObj *vm, + bool tlsListen, + int asyncJob, + char **tlsAlias, + qemuMigrationParams *migParams) +{ + qemuDomainObjPrivate *priv = vm->privateData; + g_autoptr(virJSONValue) tlsPSKProps = NULL; + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + g_autofree char *key_dir_path = NULL; + g_autofree char *shortName = NULL; + virErrorPtr orig_err = NULL; + + if (!(shortName = virDomainDefGetShortName(vm->def))) + return -1; + + key_dir_path = g_strdup_printf("%s/%s", cfg->tlsPSKStateDir, shortName); + + if (!(*tlsAlias = qemuAliasTLSObjFromSrcAlias(QEMU_MIGRATION_TLS_ALIAS_BASE))) + return -1; + + if (qemuBuildTLSPSKBackendProps(key_dir_path, tlsListen, *tlsAlias, &tlsPSKProps) < 0) + return -1; + + /* Ensure the domain doesn't already have the TLS-PSK objects defined. + * This should prevent any issues just in case some cleanup wasn't + * properly completed (both src and dst use the same alias) or + * some other error path. */ + qemuDomainDelTLSObjects(vm, asyncJob, NULL, *tlsAlias); + + + /* Add the tls-creds-psk object to QEMU */ + if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0) + return -1; + + if (qemuMonitorAddObject(priv->mon, &tlsPSKProps, NULL) < 0) { + virErrorPreserveLast(&orig_err); + qemuDomainObjExitMonitor(vm); + virErrorRestore(&orig_err); + return -1; + } + qemuDomainObjExitMonitor(vm); + + if (qemuMigrationParamsSetString(migParams, QEMU_MIGRATION_PARAM_TLS_CREDS, + *tlsAlias) < 0) + return -1; + + return 0; +} + + /* qemuMigrationParamsDisableTLS * @vm: domain object * @migParams: Pointer to a migration parameters block diff --git a/src/qemu/qemu_migration_params.h b/src/qemu/qemu_migration_params.h index 14e20fb71e..8774b4596c 100644 --- a/src/qemu/qemu_migration_params.h +++ b/src/qemu/qemu_migration_params.h @@ -123,6 +123,14 @@ qemuMigrationParamsEnableTLSx509(virQEMUDriver *driver, const char *hostname, qemuMigrationParams *migParams); +int +qemuMigrationParamsEnableTLSPSK(virQEMUDriver *driver, + virDomainObj *vm, + bool tlsListen, + int asyncJob, + char **tlsAlias, + qemuMigrationParams *migParams); + int qemuMigrationParamsDisableTLS(virDomainObj *vm, qemuMigrationParams *migParams); -- 2.43.7
Enable TLS-PSK based secure migration, if and only if both source and destination supports the tls-creds-psk object. Suggested-by: Tejus GK <tejus.gk@nutanix.com> Signed-off-by: Abhisek Panda <abhisek.panda1@nutanix.com> --- include/libvirt/libvirt-domain.h | 10 ++++-- src/qemu/qemu_migration.c | 56 ++++++++++++++++++++++++-------- 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 99208137c3..2ec3956f8b 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -1089,9 +1089,13 @@ typedef enum { VIR_MIGRATE_POSTCOPY = (1 << 15), /* Setting the VIR_MIGRATE_TLS flag will cause the migration to attempt - * to use the TLS environment configured by the hypervisor in order to - * perform the migration. If incorrectly configured on either source or - * destination, the migration will fail. + * to use the TLS X.509 authentication mechanisms only if the TLS pre-shared + * key (PSK) authentication mechanism is not supported by either source + * or destination. If the certificate or the key files are incorrectly configured + * on either source or destination, then the migration will fail. + * + * Note: Since 12.7.0, Libvirt supports the TLS pre-shared key (PSK) authentication + * mechanism along with the TLS X.509 authentication scheme. * * Since: 3.2.0 */ diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 2fc8af9c15..e9c8ddc343 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -3499,9 +3499,19 @@ qemuMigrationDstPrepareActive(virQEMUDriver *driver, /* Save original migration parameters */ qemuDomainSaveStatus(vm); - /* Migrations using TLS need to add the "tls-creds-x509" object and - * set the migration TLS parameters */ - if (flags & VIR_MIGRATE_TLS) { + /* Migrations need to add the "tls-creds-psk" object whenever both + * sides support TLS-PSK authentication regardless of the + * VIR_MIGRATE_TLS flag. Otherwise, fall back to "tls-creds-x509" if + * VIR_MIGRATE_TLS is enabled. Finally, set the appropriate migration + * TLS parameters. */ + if ((mig->flags & QEMU_MIGRATION_COOKIE_TLS_PSK) && mig->tlsPSK) { + if (qemuMigrationPersistPSK(driver, vm, mig->tlsPSK) < 0) + goto error; + if (qemuMigrationParamsEnableTLSPSK(driver, vm, true, + VIR_ASYNC_JOB_MIGRATION_IN, + &tlsAlias, migParams) < 0) + goto error; + } else if (flags & VIR_MIGRATE_TLS) { if (qemuMigrationParamsEnableTLSx509(driver, vm, true, VIR_ASYNC_JOB_MIGRATION_IN, &tlsAlias, NULL, @@ -3516,14 +3526,13 @@ qemuMigrationDstPrepareActive(virQEMUDriver *driver, flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC)) { const char *nbdTLSAlias = NULL; - if (flags & VIR_MIGRATE_TLS) { - if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NBD_TLS)) { - virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", - _("QEMU NBD server does not support TLS transport")); - goto error; - } - + if (tlsAlias && virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NBD_TLS)) { nbdTLSAlias = tlsAlias; + } else if ((flags & VIR_MIGRATE_TLS) && + !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NBD_TLS)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("QEMU NBD server does not support TLS transport")); + goto error; } if (qemuMigrationDstStartNBDServer(driver, vm, incoming->address, @@ -3611,7 +3620,7 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver, qemuDomainObjPrivate *priv = NULL; g_autoptr(qemuMigrationCookie) mig = NULL; g_autofree char *xmlout = NULL; - unsigned int cookieFlags = 0; + unsigned int cookieFlags = QEMU_MIGRATION_COOKIE_TLS_PSK; bool taint_hook = false; VIR_DEBUG("name=%s, origname=%s, protocol=%s, port=%hu, " @@ -3677,7 +3686,8 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver, QEMU_MIGRATION_COOKIE_CPU_HOTPLUG | QEMU_MIGRATION_COOKIE_CPU | QEMU_MIGRATION_COOKIE_CAPS | - QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS))) + QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS | + QEMU_MIGRATION_COOKIE_TLS_PSK))) goto cleanup; if (!(vm = virDomainObjListAdd(driver->domains, def, @@ -5102,6 +5112,9 @@ qemuMigrationSrcRun(virQEMUDriver *driver, if (storageMigration) cookieFlags |= QEMU_MIGRATION_COOKIE_NBD; + if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_TLS_CREDS_PSK)) + cookieFlags |= QEMU_MIGRATION_COOKIE_TLS_PSK; + if (virLockManagerPluginUsesState(driver->lockManager) && !cookieout) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -5152,7 +5165,12 @@ qemuMigrationSrcRun(virQEMUDriver *driver, /* Save original migration parameters */ qemuDomainSaveStatus(vm); - if (flags & VIR_MIGRATE_TLS) { + if (mig->flags & QEMU_MIGRATION_COOKIE_TLS_PSK) { + if (qemuMigrationParamsEnableTLSPSK(driver, vm, false, + VIR_ASYNC_JOB_MIGRATION_OUT, + &tlsAlias, migParams) < 0) + goto error; + } else if (flags & VIR_MIGRATE_TLS) { const char *hostname = NULL; /* We need to add tls-hostname whenever QEMU itself does not @@ -5201,6 +5219,7 @@ qemuMigrationSrcRun(virQEMUDriver *driver, if (storageMigration) { const char *host = ""; const char *tlsHostname = qemuMigrationParamsGetTLSHostname(migParams); + const char *nbdTLSAlias = NULL; if (!mig->nbd) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -5213,13 +5232,22 @@ qemuMigrationSrcRun(virQEMUDriver *driver, host = spec->dest.host.name; } + if (tlsAlias && virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NBD_TLS)) { + nbdTLSAlias = tlsAlias; + } else if ((flags & VIR_MIGRATE_TLS) && + !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NBD_TLS)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("QEMU NBD client does not support TLS transport")); + goto error; + } + if (qemuMigrationSrcNBDStorageCopy(driver, vm, mig, host, priv->migMaxBandwidth, migrate_disks, migrate_disks_detect_zeroes, migrate_disks_target_zero, - dconn, tlsAlias, tlsHostname, + dconn, nbdTLSAlias, tlsHostname, nbdURI, flags) < 0) { goto error; } -- 2.43.7
In the case of TLS-PSK-enabled migration, Libvirt manages the lifecycle of the pre-shared key. Add a new test scenario to the migration cookie test suite to validate the generation of pre-shared key when the QEMU_MIGRATION_COOKIE_TLS_PSK flag is set. In addition, the test also checks the length and the hexadecimal encoding of the pre-shared key. Signed-off-by: Abhisek Panda <abhisek.panda1@nutanix.com> --- tests/qemumigrationcookiexmltest.c | 123 +++++++++++++++++++++++++++++ tests/testutilsqemu.c | 12 +++ 2 files changed, 135 insertions(+) diff --git a/tests/qemumigrationcookiexmltest.c b/tests/qemumigrationcookiexmltest.c index 41846b8631..60ca62f98a 100644 --- a/tests/qemumigrationcookiexmltest.c +++ b/tests/qemumigrationcookiexmltest.c @@ -16,6 +16,7 @@ #include <config.h> +#include <stddef.h> #include <unistd.h> #include <sys/types.h> @@ -92,6 +93,99 @@ testQemuMigrationCookieDataFree(struct testQemuMigrationCookieData *data) } +static int +testQemuMigrationCookiePSKValidate(const char *key) +{ + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(&driver); + size_t expected_key_len = 2 * cfg->migrateTLSPSKLength; /* The pre-shared key's length is 2 * PSK length */ + size_t i; + + if (!key) { + VIR_TEST_DEBUG("\nThe pre-shared key is not present in the migration cookie."); + return -1; + } + + if (strlen(key) != expected_key_len) { + VIR_TEST_DEBUG("\nThe length of the pre-shared key is incorrect."); + return -1; + } + + /* Check the characters of the key */ + for (i = 0; i < expected_key_len; i++) { + if (!g_ascii_isxdigit(key[i])) { + VIR_TEST_DEBUG("\nThe key contains non-hex characters"); + return -1; + } + } + + return 0; +} + + +static int +testQemuMigrationCookiePSKAttribute(const void *opaque) +{ + struct testQemuMigrationCookieData *data = (struct testQemuMigrationCookieData *) opaque; + g_autoptr(qemuMigrationCookie) cookie = NULL; + qemuDomainObjPrivate *priv; + + /* if the VM object parsing step failed there's nothing this test can do */ + if (!data->vm) { + VIR_TEST_DEBUG("\nmissing VM object\n"); + return -1; + } + priv = data->vm->privateData; + + if (!(cookie = qemuMigrationCookieNew(data->vm->def, NULL))) + return -1; + + g_free(cookie->localHostname); + cookie->localHostname = g_strdup("hostname2"); + + if (virUUIDParse("8b3f4dc4-6a8e-5f9b-94a5-4c35babd8d95", cookie->localHostuuid) < 0) { + VIR_TEST_DEBUG("\nfailed to parse fake UUID"); + return -1; + } + + /* Format the migration cookie at the source */ + if (qemuMigrationCookieFormat(cookie, + &driver, + data->vm, + data->cookiePopulateParty, + &data->xmlstr, + &data->xmlstrlen, + data->cookiePopulateFlags) < 0) { + VIR_TEST_DEBUG("\nfailed to populate and format qemu migration cookie"); + return -1; + } + + /* Check for the <migration-key> element in the generated migration cookie XML */ + if (!strstr(data->xmlstr, "<migration-key>")) { + VIR_TEST_DEBUG("\nthe migration cookie is missing the migration-key element:\n%s\n", + data->xmlstr); + return -1; + } + + /* Parse the migration cookie at the destination */ + if (!(data->cookie = qemuMigrationCookieParse(&driver, + data->vm, + data->vm->def, + NULL, + priv->qemuCaps, + data->xmlstr, + data->xmlstrlen, + data->cookieParseFlags))) { + VIR_TEST_DEBUG("\nfailed to parse qemu migration cookie:\n%s\n", data->xmlstr); + return -1; + } + + if (testQemuMigrationCookiePSKValidate(data->cookie->tlsPSK) < 0) + return -1; + + return 0; +} + + static int testQemuMigrationCookiePopulate(const void *opaque) { @@ -418,6 +512,32 @@ testQemuMigrationCookieXML2XMLBitmaps(const char *name, return ret; } +/* tests the generation and persistence of the pre-shared keys */ +static int +testQemuMigrationCookiePSK(const char *domxml) +{ + struct testQemuMigrationCookieData *data = g_new0(struct testQemuMigrationCookieData, 1); + int ret = 0; + + data->cookiePopulateFlags = QEMU_MIGRATION_COOKIE_TLS_PSK; + data->cookiePopulateParty = QEMU_MIGRATION_SOURCE; + data->cookieParseFlags = QEMU_MIGRATION_COOKIE_TLS_PSK; + data->inStatus = g_strconcat(abs_srcdir, "/", domxml, NULL); + + /* load status XML as domain object */ + if (testQemuMigrationCookieDomInit(data) < 0) + ret = -1; + + /* test PSK generation and persistence */ + if (virTestRun("qemumigrationcookie-psk-lifecycle", + testQemuMigrationCookiePSKAttribute, data) < 0) + ret = -1; + + testQemuMigrationCookieDataFree(data); + + return ret; +} + static int mymain(void) @@ -448,6 +568,9 @@ mymain(void) if (testQemuMigrationCookieXML2XMLBitmaps("nbd-bitmaps", "qemustatusxml2xmldata/migration-out-nbd-bitmaps-in.xml", 0) < 0) ret = -1; + if (testQemuMigrationCookiePSK("qemustatusxml2xmldata/modern-in.xml") < 0) + ret = -1; + virBufferFreeAndReset(&testnamebuf); cleanup: diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c index e5e3342b53..b0e0d41895 100644 --- a/tests/testutilsqemu.c +++ b/tests/testutilsqemu.c @@ -297,6 +297,7 @@ qemuTestCapsCacheInsert(virFileCache *cache, #define STATEDIRTEMPLATE abs_builddir "/qemustatedir-XXXXXX" #define CONFIGDIRTEMPLATE abs_builddir "/qemuconfigdir-XXXXXX" +#define TLSPSKDIRTEMPLATE abs_builddir "/pskstatedir-XXXXXX" int qemuTestDriverInit(virQEMUDriver *driver) { @@ -304,6 +305,7 @@ int qemuTestDriverInit(virQEMUDriver *driver) virSecurityManager *mgr = NULL; char statedir[] = STATEDIRTEMPLATE; char configdir[] = CONFIGDIRTEMPLATE; + char tlspskdir[] = TLSPSKDIRTEMPLATE; memset(driver, 0, sizeof(*driver)); @@ -328,6 +330,7 @@ int qemuTestDriverInit(virQEMUDriver *driver) * dirs. */ VIR_FREE(cfg->stateDir); VIR_FREE(cfg->configDir); + VIR_FREE(cfg->tlsPSKStateDir); /* Override paths to ensure predictable output * @@ -367,6 +370,13 @@ int qemuTestDriverInit(virQEMUDriver *driver) cfg->configDir = g_strdup(configdir); + if (!g_mkdtemp(tlspskdir)) { + fprintf(stderr, "Cannot create fake tlsPSKStateDir"); + goto error; + } + + cfg->tlsPSKStateDir = g_strdup(tlspskdir); + driver->caps = testQemuCapsInit(); if (!driver->caps) goto error; @@ -433,6 +443,8 @@ int qemuTestDriverInit(virQEMUDriver *driver) cfg->dumpGuestCore = false; + cfg->migrateTLSPSKLength = 32; + driver->privileged = true; return 0; -- 2.43.7
On 7 Sep 2026, at 2:26 PM, Abhisek Panda <abhisek.panda1@nutanix.com> wrote:
QEMU provides the capability to encrypt the migration data stream using two transport layer security (TLS) authentication schemes: X.509 certificates and pre-shared keys (PSK). Currently, Libvirt only supports the X.509-based TLS authentication scheme. In TLS X.509 certificates, a set of live migrations utilize a fixed set of static certificates for encrypted migration. In this authentication scheme, users require to deploy a certificate authority and monitor the certificate expiration window. In case certificates are compromised all the future live migrations are vulnerable.
To resolve this, this patch series introduce the support for pre-shared key-based authentication scheme. This mechanism relies on symmetric pre-shared keys (a secret key that is known to both sender and receiver prior to secure communication) for providing secure transfer of data. Libvirt solely manages the lifecycle of the ephemeral pre-shared keys, including, generation, persistent storage, and cleanup. Libvirt generates the key on the source machine, then transfers it to the destination machine using the migration cookie. To allow users to configure the size of the key, Libvirt provides the migrate_tls_psk_length configuration parameter in qemu.conf.
We enable the PSK-based TLS authentication scheme if both source and destination supports the tls-creds-psk object regardless of the value of VIR_MIGRATE_TLS flag. Else, we use the X.509-based TLS authentication scheme if the VIR_MIGRATE_TLS flag is set.
v4: 1. Enable TLS-PSK if source and destination supports it regardless of the VIR_MIGRATE_TLS flag. 2. If either source or destination does not support TLS-PSK and the VIR_MIGRATE_TLS flag is set then fallback to TLS X509
v3: 1. Destination host decides which TLS authentication scheme to use. 2. The directory of the key file is set to <tls_psk_state_dir>/$ID-$VMNAME. 3. Use the same alias for both tls-creds-x509 and tls-creds-psk objects. 4. Validate the length of the pre-shared key. 5. Unit test to validate the pre-shared key in the migration cookie.
v2: 1. Libvirt manages the lifecycle of pre-shared keys. 2. Transfer of keys to the destination via the migration cookie 3. Remove the VIR_MIGRATE_TLS_PSK flag instead rely on VIR_MIGRATE_TLS and availability of ca-cert.pem on source. 4. Drop VIR_MIGRATE_PARAM_TLS_PSK_DIRECTORY, Libvirt solely manages the pre-shared keys.
Abhisek Panda (7): conf: Add a configuration param for TLS-PSK qemu: Manage a pre-shared key's lifecycle qemu: Add support to build the tls-creds-psk object qemu: rename tls-creds-x509 obj related functions qemu: Manage tls-creds-psk object lifecycle qemu: Set up the migrate TLS-PSK objects tests: Add testing of pre-shared key lifecycle
include/libvirt/libvirt-domain.h | 10 +- src/qemu/libvirtd_qemu.aug | 1 + src/qemu/qemu.conf.in | 8 + src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 26 +++ src/qemu/qemu_command.h | 7 + src/qemu/qemu_conf.c | 22 +++ src/qemu/qemu_conf.h | 2 + src/qemu/qemu_domain.c | 1 + src/qemu/qemu_domain.h | 1 + src/qemu/qemu_driver.c | 6 + src/qemu/qemu_hotplug.c | 40 ++--- src/qemu/qemu_hotplug.h | 24 +-- src/qemu/qemu_migration.c | 170 +++++++++++++++--- src/qemu/qemu_migration.h | 3 + src/qemu/qemu_migration_cookie.c | 79 +++++++- src/qemu/qemu_migration_cookie.h | 5 + src/qemu/qemu_migration_params.c | 98 ++++++++-- src/qemu/qemu_migration_params.h | 22 ++- src/qemu/qemu_process.c | 3 + src/qemu/test_libvirtd_qemu.aug.in | 1 + .../caps_10.0.0_aarch64.xml | 1 + .../caps_10.0.0_ppc64.xml | 1 + .../caps_10.0.0_s390x.xml | 1 + .../caps_10.0.0_x86_64+amdsev.xml | 1 + .../caps_10.0.0_x86_64.xml | 1 + .../caps_10.1.0_s390x.xml | 1 + .../caps_10.1.0_x86_64+inteltdx.xml | 1 + .../caps_10.1.0_x86_64.xml | 1 + .../caps_10.2.0_aarch64.xml | 1 + .../caps_10.2.0_x86_64+mshv.xml | 1 + .../caps_10.2.0_x86_64.xml | 1 + .../caps_11.0.0_aarch64.xml | 1 + .../caps_11.0.0_s390x.xml | 1 + .../caps_11.0.0_x86_64+sgx.xml | 1 + .../caps_11.0.0_x86_64.xml | 1 + .../caps_11.1.0_aarch64.xml | 1 + .../caps_11.1.0_s390x.xml | 1 + .../caps_11.1.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml | 1 + .../caps_7.2.0_x86_64+hvf.xml | 1 + .../caps_7.2.0_x86_64.xml | 1 + .../caps_8.0.0_x86_64.xml | 1 + .../qemucapabilitiesdata/caps_8.1.0_s390x.xml | 1 + .../caps_8.1.0_x86_64.xml | 1 + .../caps_8.2.0_aarch64.xml | 1 + .../caps_8.2.0_armv7l.xml | 1 + .../caps_8.2.0_loongarch64.xml | 1 + .../qemucapabilitiesdata/caps_8.2.0_s390x.xml | 1 + .../caps_8.2.0_x86_64.xml | 1 + .../qemucapabilitiesdata/caps_9.0.0_sparc.xml | 1 + .../caps_9.0.0_x86_64.xml | 1 + .../caps_9.1.0_riscv64.xml | 1 + .../qemucapabilitiesdata/caps_9.1.0_s390x.xml | 1 + .../caps_9.1.0_x86_64.xml | 1 + .../caps_9.2.0_aarch64+hvf.xml | 1 + .../qemucapabilitiesdata/caps_9.2.0_s390x.xml | 1 + .../caps_9.2.0_x86_64+amdsev.xml | 1 + .../caps_9.2.0_x86_64.xml | 1 + tests/qemumigrationcookiexmltest.c | 135 +++++++++++++- tests/testutilsqemu.c | 12 ++ 62 files changed, 632 insertions(+), 85 deletions(-)
-- 2.43.7
Ping for the series. Checking in to see if anyone has feedback on this patch set. Thanks and warm regards Dr. Abhisek Panda
participants (1)
-
Abhisek Panda