> On 13 Jul 2026, at 7:05 PM, Peter Krempa <[email protected]> wrote: > > !-------------------------------------------------------------------| > CAUTION: External Email > > |-------------------------------------------------------------------! > > On Tue, Jun 23, 2026 at 06:26:04 +0000, Abhisek Panda wrote: >> On the source host enable TLS-PSK based secure migration, if and only >> if the VIR_MIGRATE_TLS flag is set and ca-cert.pem does not exist. >> This is because the TLS X.509-based migration utilize the ca-cert.pem >> file to verify the destination host. Subsequently, the source generates >> a pre-shared key and transmits it to the destination via a migration >> cookie. On the destination host, Libvirt unconditionally enables >> PSK-based migration if it receives the key via the cookie. >> >> Suggested-by: Tejus GK <[email protected]> >> Signed-off-by: Abhisek Panda <[email protected]> >> --- >> include/libvirt/libvirt-domain.h | 13 ++++-- >> src/qemu/qemu_migration.c | 74 ++++++++++++++++++++------------ >> 2 files changed, 56 insertions(+), 31 deletions(-) >> >> diff --git a/include/libvirt/libvirt-domain.h >> b/include/libvirt/libvirt-domain.h >> index 5b67f8f897..e8b5d8451c 100644 >> --- a/include/libvirt/libvirt-domain.h >> +++ b/include/libvirt/libvirt-domain.h >> @@ -1089,11 +1089,16 @@ 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 either the TLS X.509 or TLS pre-shared key (PSK) >> authentication >> + * mechanisms. If valid certificates and keys are present on the >> + * host, then TLS X.509 authentication scheme is used. However, if >> ca-cert.pem >> + * is missing on the source, then TLS PSK authentication scheme is used. >> + * In this case, the client must use a secure Libvirt to Libvirt >> communication >> + * channel because the pre-shared key is transmitted to the destination >> using the > > The user ought to always use secure libvirt mode. No need to mention it > explicitly. > >> + * migration cookie. If the certificate or the key file is corrupted or >> not >> + * properly configured on either source or destination, the migration >> will fail. > > This will need to be updated after the changes I've suggested. > >> * >> - * Since: 3.2.0 >> + * Since: 12.4.0 > > You can't change version info of an existing flag. This shows since when > the flag exists. > > >> */ >> VIR_MIGRATE_TLS = (1 << 16), >> >> diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c >> index 79b93fb6e9..bac5a953d1 100644 >> --- a/src/qemu/qemu_migration.c >> +++ b/src/qemu/qemu_migration.c >> @@ -3360,6 +3360,7 @@ qemuMigrationDstPrepareActive(virQEMUDriver *driver, >> qemuDomainJobPrivate *jobPriv = vm->job->privateData; >> qemuProcessIncomingDef *incoming = NULL; >> g_autofree char *tlsx509Alias = NULL; >> + g_autofree char *tlsPSKAlias = NULL; >> virObjectEvent *event = NULL; >> virErrorPtr origErr = NULL; >> int dataFD[2] = { -1, -1 }; >> @@ -3442,14 +3443,22 @@ qemuMigrationDstPrepareActive(virQEMUDriver *driver, >> /* Save original migration parameters */ >> qemuDomainSaveStatus(vm); >> >> - /* Migrations using TLS need to add the "tls-creds-x509" object and >> + /* Migrations using TLS need to add the "tls-creds-x509" object if the >> cert files are >> + * present on the host, else fallback to adding the "tls-creds-psk" >> object. Additionally, >> * set the migration TLS parameters */ >> if (flags & VIR_MIGRATE_TLS) { >> - if (qemuMigrationParamsEnableTLSx509(driver, vm, true, >> - VIR_ASYNC_JOB_MIGRATION_IN, >> - &tlsx509Alias, NULL, >> - migParams) < 0) >> - goto error; >> + if (!mig->tlsPSK) { >> + if (qemuMigrationParamsEnableTLSx509(driver, vm, true, >> + VIR_ASYNC_JOB_MIGRATION_IN, >> + &tlsx509Alias, NULL, >> + migParams) < 0) >> + goto error; >> + } else { >> + if (qemuMigrationParamsEnableTLSPSK(driver, vm, true, >> + VIR_ASYNC_JOB_MIGRATION_IN, >> + &tlsPSKAlias, migParams) < >> 0) >> + goto error; >> + } >> } else { >> if (qemuMigrationParamsDisableTLS(vm, migParams) < 0) >> goto error; >> @@ -3556,6 +3565,13 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver, >> g_autofree char *xmlout = NULL; >> unsigned int cookieFlags = 0; >> bool taint_hook = false; >> + unsigned int parseCookieFlags = QEMU_MIGRATION_COOKIE_LOCKSTATE | >> + QEMU_MIGRATION_COOKIE_NBD | >> + QEMU_MIGRATION_COOKIE_MEMORY_HOTPLUG | >> + QEMU_MIGRATION_COOKIE_CPU_HOTPLUG | >> + QEMU_MIGRATION_COOKIE_CPU | >> + QEMU_MIGRATION_COOKIE_CAPS | >> + >> QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS; >> >> VIR_DEBUG("name=%s, origname=%s, protocol=%s, port=%hu, " >> "listenAddress=%s, nbdPort=%d, nbdURI=%s, flags=0x%x", >> @@ -3567,6 +3583,9 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver, >> QEMU_MIGRATION_COOKIE_CAPS; >> } >> >> + if (flags & VIR_MIGRATE_TLS) >> + parseCookieFlags |= QEMU_MIGRATION_COOKIE_TLS_PSK; >> + >> /* Let migration hook filter domain XML */ >> if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) { >> g_autofree char *xml = NULL; >> @@ -3613,14 +3632,7 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver, >> * domain list. Parsing/validation may fail and there's no >> * point in having the domain in the list at that point. */ >> if (!(mig = qemuMigrationCookieParse(driver, NULL, *def, origname, NULL, >> - cookiein, cookieinlen, >> - QEMU_MIGRATION_COOKIE_LOCKSTATE | >> - QEMU_MIGRATION_COOKIE_NBD | >> - >> QEMU_MIGRATION_COOKIE_MEMORY_HOTPLUG | >> - QEMU_MIGRATION_COOKIE_CPU_HOTPLUG | >> - QEMU_MIGRATION_COOKIE_CPU | >> - QEMU_MIGRATION_COOKIE_CAPS | >> - >> QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS))) >> + cookiein, cookieinlen, >> parseCookieFlags))) >> goto cleanup; > > > Destination should always parse the PSK. If it's missing there's nothing > to do but if the source sent it we should use it (to ensure > always-secure mode). > > >> >> if (!(vm = virDomainObjListAdd(driver->domains, def, >> @@ -5013,6 +5025,7 @@ qemuMigrationSrcRun(virQEMUDriver *driver, >> qemuDomainObjPrivate *priv = vm->privateData; >> g_autoptr(qemuMigrationCookie) mig = NULL; >> g_autofree char *tlsx509Alias = NULL; >> + g_autofree char *tlsPSKAlias = NULL; >> qemuMigrationIOThread *iothread = NULL; >> VIR_AUTOCLOSE fd = -1; >> unsigned long restore_max_bandwidth = priv->migMaxBandwidth; >> @@ -5097,19 +5110,26 @@ qemuMigrationSrcRun(virQEMUDriver *driver, >> qemuDomainSaveStatus(vm); >> >> if (flags & VIR_MIGRATE_TLS) { >> - const char *hostname = NULL; >> - >> - /* We need to add tls-hostname whenever QEMU itself does not >> - * connect directly to the destination. */ >> - if (spec->destType == MIGRATION_DEST_CONNECT_HOST || >> - spec->destType == MIGRATION_DEST_FD) >> - hostname = spec->dest.host.name; >> - >> - if (qemuMigrationParamsEnableTLSx509(driver, vm, false, >> - VIR_ASYNC_JOB_MIGRATION_OUT, >> - &tlsx509Alias, hostname, >> - migParams) < 0) >> - goto error; >> + if (qemuMigrationCACertExists(driver)) { > > Here this decision should happen based on whether the destination > libvirt instance accepted PSK or not; deciding based on existance of the > x509 key on the source will not allow ever using the PSK if the > destionation doesn't have those set up. > > >> + const char *hostname = NULL; >> + >> + /* We need to add tls-hostname whenever QEMU itself does not >> + * connect directly to the destination. */ >> + if (spec->destType == MIGRATION_DEST_CONNECT_HOST || >> + spec->destType == MIGRATION_DEST_FD) >> + hostname = spec->dest.host.name; >> + >> + if (qemuMigrationParamsEnableTLSx509(driver, vm, false, >> + >> VIR_ASYNC_JOB_MIGRATION_OUT, >> + &tlsx509Alias, hostname, >> + migParams) < 0) >> + goto error; >> + } else { >> + if (qemuMigrationParamsEnableTLSPSK(driver, vm, false, >> + VIR_ASYNC_JOB_MIGRATION_OUT, >> + &tlsPSKAlias, migParams) < >> 0) >> + goto error; >> + } >> } else { >> if (qemuMigrationParamsDisableTLS(vm, migParams) < 0) >> goto error; >> -- >> 2.43.7
Addressed in v3.
