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
+     * 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

Reply via email to