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 <tejus.gk@nutanix.com> Signed-off-by: Abhisek Panda <abhisek.panda1@nutanix.com> --- 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 + * migration cookie. If the certificate or the key file is corrupted or not + * properly configured on either source or destination, the migration will fail. * - * Since: 3.2.0 + * Since: 12.4.0 */ 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; 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)) { + 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