Enable TLS-PSK based secure migration, if the source provides the
pre-shared key in the migration cookie else fall back to X.509-based
secure migration.

Suggested-by: Tejus GK <[email protected]>
Signed-off-by: Abhisek Panda <[email protected]>
---
 include/libvirt/libvirt-domain.h | 10 ++++--
 src/qemu/qemu_migration.c        | 59 +++++++++++++++++++++++---------
 2 files changed, 49 insertions(+), 20 deletions(-)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 9ee153c6eb..f3e72065a9 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 provided by the source.
+     * 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 ce791bd3ba..c958edef6a 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -3500,9 +3500,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,
@@ -3517,14 +3527,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,
@@ -3612,7 +3621,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, "
@@ -3621,8 +3630,8 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver,
               listenAddress, nbdPort, NULLSTR(nbdURI), flags);
 
     if (!(flags & VIR_MIGRATE_OFFLINE)) {
-        cookieFlags = QEMU_MIGRATION_COOKIE_GRAPHICS |
-                      QEMU_MIGRATION_COOKIE_CAPS;
+        cookieFlags |= QEMU_MIGRATION_COOKIE_GRAPHICS |
+                       QEMU_MIGRATION_COOKIE_CAPS;
     }
 
     /* Let migration hook filter domain XML */
@@ -3678,7 +3687,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,
@@ -5080,7 +5090,7 @@ qemuMigrationSrcRun(virQEMUDriver *driver,
     VIR_AUTOCLOSE fd = -1;
     unsigned long restore_max_bandwidth = priv->migMaxBandwidth;
     virErrorPtr orig_err = NULL;
-    unsigned int cookieFlags = QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS;
+    unsigned int cookieFlags = QEMU_MIGRATION_COOKIE_BLOCK_DIRTY_BITMAPS | 
QEMU_MIGRATION_COOKIE_TLS_PSK;
     bool abort_on_error = !!(flags & VIR_MIGRATE_ABORT_ON_ERROR);
     bool storageMigration = flags & (VIR_MIGRATE_NON_SHARED_DISK | 
VIR_MIGRATE_NON_SHARED_INC);
     bool cancel = false;
@@ -5159,7 +5169,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
@@ -5208,6 +5223,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",
@@ -5220,13 +5236,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

Reply via email to