Use the migrate_tls_force configuration param to control whether encrypted migration is mandatory. When enabled, libvirt unconditionally attempts the TLS pre-shared key authentication mechanism during migration and fails the migration if the peer does not agree to it. When disabled, the TLS authentication mechanisms are used only when the VIR_MIGRATE_TLS flag is set; otherwise unencrypted migration remains permitted. Signed-off-by: Abhisek Panda <abhisek.panda1@nutanix.com> --- src/qemu/qemu.conf.in | 12 ++++++---- src/qemu/qemu_migration.c | 48 +++++++++++++++++++-------------------- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/qemu/qemu.conf.in b/src/qemu/qemu.conf.in index 4fdd655881..80ba46aca8 100644 --- a/src/qemu/qemu.conf.in +++ b/src/qemu/qemu.conf.in @@ -429,10 +429,14 @@ #migrate_tls_priority = "@SYSTEM" -# By default TLS is requested using the VIR_MIGRATE_TLS flag, thus not requested -# automatically. Setting 'migate_tls_force' to "1" will prevent any migration -# which is not using VIR_MIGRATE_TLS to ensure higher level of security in -# deployments with TLS. +# Enforce TLS encryption for all domain migrations using either X.509 certificates +# or pre-shared keys (PSK) authentication schemes. By default, Libvirt allows +# unencrypted migrations to proceed whenever the VIR_MIGRATE_TLS flag is not +# explicitly set in migration. +# +# Enabling this option strictly prohibits unencrypted migrations to proceed. +# If the destination fails to negotiate TLS, migration fails immediately +# rather than falling back to unencrypted migration. # #migrate_tls_force = 0 diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index c958edef6a..7716419a40 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -2892,7 +2892,8 @@ qemuMigrationSrcBeginPhase(virQEMUDriver *driver, unsigned int flags) { qemuDomainObjPrivate *priv = vm->privateData; - unsigned int cookieFlags = QEMU_MIGRATION_COOKIE_LOCKSTATE | QEMU_MIGRATION_COOKIE_TLS_PSK; + unsigned int cookieFlags = QEMU_MIGRATION_COOKIE_LOCKSTATE; + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); VIR_DEBUG("driver=%p, vm=%p, xmlin=%s, dname=%s," " cookieout=%p, cookieoutlen=%p," @@ -2958,6 +2959,9 @@ qemuMigrationSrcBeginPhase(virQEMUDriver *driver, return NULL; } + if (cfg->migrateTLSForce || (flags & VIR_MIGRATE_TLS)) + cookieFlags |= QEMU_MIGRATION_COOKIE_TLS_PSK; + if (flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC)) { if (flags & VIR_MIGRATE_TUNNELLED) { virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", @@ -3167,14 +3171,6 @@ qemuMigrationSrcBegin(virConnectPtr conn, g_autofree char *xml = NULL; char *ret = NULL; - if (cfg->migrateTLSForce && - !(flags & VIR_MIGRATE_TUNNELLED) && - !(flags & VIR_MIGRATE_TLS)) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("this libvirtd instance allows migration only with VIR_MIGRATE_TLS flag")); - goto cleanup; - } - if (flags & VIR_MIGRATE_POSTCOPY_RESUME) { ret = qemuMigrationSrcBeginResumePhase(conn, vm, xmlin, cookieout, cookieoutlen, flags); @@ -3623,6 +3619,7 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver, g_autofree char *xmlout = NULL; unsigned int cookieFlags = QEMU_MIGRATION_COOKIE_TLS_PSK; bool taint_hook = false; + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); VIR_DEBUG("name=%s, origname=%s, protocol=%s, port=%hu, " "listenAddress=%s, nbdPort=%d, nbdURI=%s, flags=0x%x", @@ -3691,6 +3688,14 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver, QEMU_MIGRATION_COOKIE_TLS_PSK))) goto cleanup; + if (!mig->tlsPSK && + cfg->migrateTLSForce && + !(flags & VIR_MIGRATE_TLS)) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("The destination host only supports encrypted migration")); + goto cleanup; + } + if (!(vm = virDomainObjListAdd(driver->domains, def, driver->xmlopt, VIR_DOMAIN_OBJ_LIST_ADD_LIVE | @@ -3924,14 +3929,6 @@ qemuMigrationDstPrepareAny(virQEMUDriver *driver, return -1; } - if (cfg->migrateTLSForce && - !(flags & VIR_MIGRATE_TUNNELLED) && - !(flags & VIR_MIGRATE_TLS)) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("this libvirtd instance allows migration only with VIR_MIGRATE_TLS flag")); - return -1; - } - if (flags & VIR_MIGRATE_POSTCOPY_RESUME) { return qemuMigrationDstPrepareResume(driver, dconn, cookiein, cookieinlen, cookieout, cookieoutlen, @@ -5085,6 +5082,7 @@ qemuMigrationSrcRun(virQEMUDriver *driver, int ret = -1; qemuDomainObjPrivate *priv = vm->privateData; g_autoptr(qemuMigrationCookie) mig = NULL; + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); g_autofree char *tlsAlias = NULL; qemuMigrationIOThread *iothread = NULL; VIR_AUTOCLOSE fd = -1; @@ -5158,6 +5156,14 @@ qemuMigrationSrcRun(virQEMUDriver *driver, if (qemuMigrationSrcGraphicsRelocate(vm, mig, graphicsuri) < 0) VIR_WARN("unable to provide data for graphics client relocation"); + if (cfg->migrateTLSForce && + !(mig->flags & QEMU_MIGRATION_COOKIE_TLS_PSK) && + !(flags & VIR_MIGRATE_TLS)) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("The source host only supports encrypted migration")); + goto error; + } + if (mig->blockDirtyBitmaps && qemuMigrationSrcRunPrepareBlockDirtyBitmaps(vm, mig, migParams, flags) < 0) goto error; @@ -6681,14 +6687,6 @@ qemuMigrationSrcPerform(virQEMUDriver *driver, NULLSTR(cookiein), cookieinlen, cookieout, cookieoutlen, flags, NULLSTR(dname), bandwidth, v3proto); - if (cfg->migrateTLSForce && - !(flags & VIR_MIGRATE_TUNNELLED) && - !(flags & VIR_MIGRATE_TLS)) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("this libvirtd instance allows migration only with VIR_MIGRATE_TLS flag")); - return -1; - } - if ((flags & (VIR_MIGRATE_TUNNELLED | VIR_MIGRATE_PEER2PEER))) { if (cookieinlen) { virReportError(VIR_ERR_OPERATION_INVALID, -- 2.43.7