Support TLS for a migration is a multistep process. The target guest must be started using the "-object tls-creds-x509,endpoint=server,...". If that TLS object requires a passphrase an addition "-object security..." would also be created. The alias/id used for the TLS object is "objmigrate_tls0", while the alias/id used for the security object is "migrate-secret0". Once the domain is started, the "tls-creds" migration parameter must be set to the alias/id of the "tls-creds-x509" object. Once the migration completes, removing the two objects is necessary since the newly started domain could then become the source of a migration and thus would not be an endpoint. Handle the possibility of libvirtd stop/reconnect by saving the fact that a migration is using TLS was started in a "migrateTLS" boolean. Signed-off-by: John Ferlan <jferlan@xxxxxxxxxx> --- src/qemu/qemu_command.c | 29 ++++++++++++++++- src/qemu/qemu_command.h | 4 ++- src/qemu/qemu_domain.c | 5 +++ src/qemu/qemu_domain.h | 1 + src/qemu/qemu_migration.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_process.c | 4 +++ 6 files changed, 121 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index d831d56..d8373aa 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -802,6 +802,27 @@ qemuBuildTLSx509CommandLine(virCommandPtr cmd, } +static int +qemuBuildMigrateTLSCommandLine(virCommandPtr cmd, + virQEMUDriverConfigPtr cfg, + virQEMUCapsPtr qemuCaps, + qemuDomainSecretInfoPtr migSecinfo) +{ + if (migSecinfo && qemuBuildObjectSecretCommandLine(cmd, migSecinfo) < 0) + return -1; + + /* When starting from command line this is the target of a migration + * so we need to start a TLS endpoint server (3rd param) */ + if (qemuBuildTLSx509CommandLine(cmd, cfg->migrateTLSx509certdir, + true, cfg->migrateTLSx509verify, + !!cfg->migrateTLSx509secretUUID, + "migrate", qemuCaps) < 0) + return -1; + + return 0; +} + + #define QEMU_DEFAULT_NBD_PORT "10809" #define QEMU_DEFAULT_GLUSTER_PORT "24007" @@ -9639,6 +9660,8 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, bool monitor_json, virQEMUCapsPtr qemuCaps, const char *migrateURI, + bool migrateTLS, + qemuDomainSecretInfoPtr migSecinfo, virDomainSnapshotObjPtr snapshot, virNetDevVPortProfileOp vmop, bool standalone, @@ -9831,8 +9854,12 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, if (qemuBuildHostdevCommandLine(cmd, def, qemuCaps, &bootHostdevNet) < 0) goto error; - if (migrateURI) + if (migrateURI) { virCommandAddArgList(cmd, "-incoming", migrateURI, NULL); + if (migrateTLS && qemuBuildMigrateTLSCommandLine(cmd, cfg, qemuCaps, + migSecinfo) < 0) + goto error; + } if (qemuBuildMemballoonCommandLine(cmd, def, qemuCaps) < 0) goto error; diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 69fe846..d6349be 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -50,6 +50,8 @@ virCommandPtr qemuBuildCommandLine(virQEMUDriverPtr driver, bool monitor_json, virQEMUCapsPtr qemuCaps, const char *migrateURI, + bool migrateTLS, + qemuDomainSecretInfoPtr migSecinfo, virDomainSnapshotObjPtr snapshot, virNetDevVPortProfileOp vmop, bool standalone, @@ -58,7 +60,7 @@ virCommandPtr qemuBuildCommandLine(virQEMUDriverPtr driver, size_t *nnicindexes, int **nicindexes, const char *domainLibDir) - ATTRIBUTE_NONNULL(15); + ATTRIBUTE_NONNULL(17); /* Generate the object properties for a secret */ diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index dd3cfd5..100ab9c 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1864,6 +1864,9 @@ qemuDomainObjPrivateXMLFormat(virBufferPtr buf, virBufferEscapeString(buf, "<channelTargetDir path='%s'/>\n", priv->channelTargetDir); + if (priv->migrateTLS) + virBufferAddLit(buf, "<migrateTLS/>\n"); + return 0; } @@ -2132,6 +2135,8 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, if (qemuDomainSetPrivatePathsOld(driver, vm) < 0) goto error; + priv->migrateTLS = virXPathBoolean("boolean(./migrateTLS)", ctxt) == 1; + return 0; error: diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index f796306..06af44a 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -287,6 +287,7 @@ struct _qemuDomainObjPrivate { /* for migration's using TLS with a secret (not to be saved in our */ /* private XML). */ qemuDomainSecretInfoPtr migSecinfo; + bool migrateTLS; }; # define QEMU_DOMAIN_PRIVATE(vm) \ diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 0db1616..448d94e 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1487,6 +1487,55 @@ qemuMigrationEatCookie(virQEMUDriverPtr driver, return NULL; } + +/* qemuMigrationCheckSetupTLS + * + * Check if flags desired to use TLS and whether it's configured for the + * host it's being run on (src or dst depending on caller). If configured + * to use a secret for the TLS config, generate and save the migSecinfo. + * + * Returns 0 on success (or no TLS) + */ +static int +qemuMigrationCheckSetupTLS(virQEMUDriverPtr driver, + virConnectPtr dconn, + virDomainObjPtr vm, + unsigned int flags) +{ + int ret = -1; + qemuDomainObjPrivatePtr priv = vm->privateData; + virQEMUDriverConfigPtr cfg = NULL; + + if (flags & VIR_MIGRATE_TLS) { + cfg = virQEMUDriverGetConfig(driver); + + if (!cfg->migrateTLS) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("migration TLS not enabled for the host")); + goto cleanup; + } + + priv->migrateTLS = true; + if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, + vm, driver->caps) < 0) + VIR_WARN("Failed to save migrateTLS for vm %s", vm->def->name); + + /* If there's a secret associated with the migrate TLS, then we + * need to grab it before attempting to create the command line. */ + if (cfg->migrateTLSx509secretUUID && + qemuDomainSecretMigratePrepare(dconn, priv, "migrate", + cfg->migrateTLSx509secretUUID) < 0) + goto cleanup; + } + + ret = 0; + + cleanup: + virObjectUnref(cfg); + return ret; +} + + static void qemuMigrationStoreDomainState(virDomainObjPtr vm) { @@ -3613,6 +3662,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, bool stopProcess = false; bool relabel = false; int rv; + char *tlsAlias = NULL; qemuMonitorMigrationParams migParams = { 0 }; virNWFilterReadLockFilterUpdates(); @@ -3779,6 +3829,13 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, VIR_QEMU_PROCESS_START_AUTODESTROY) < 0) goto stopjob; + if (qemuMigrationCheckSetupTLS(driver, dconn, vm, flags) < 0) + goto stopjob; + + if (priv->migrateTLS && + !(tlsAlias = qemuAliasTLSObjFromSrcAlias("migrate"))) + goto stopjob; + if (qemuProcessPrepareHost(driver, vm, !!incoming) < 0) goto stopjob; @@ -3806,6 +3863,12 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, compression, &migParams) < 0) goto stopjob; + /* A set only parameter to indicate the "tls-creds-x509" object id */ + if (priv->migrateTLS) { + migParams.migrateTLSAlias = tlsAlias; + migParams.migrateTLSAlias_set = true; + } + if (STREQ_NULLABLE(protocol, "rdma") && virProcessSetMaxMemLock(vm->pid, vm->def->mem.hard_limit << 10) < 0) { goto stopjob; @@ -3891,6 +3954,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, ret = 0; cleanup: + VIR_FREE(tlsAlias); qemuProcessIncomingDefFree(incoming); VIR_FREE(xmlout); VIR_FORCE_CLOSE(dataFD[0]); @@ -6185,6 +6249,22 @@ qemuMigrationFinish(virQEMUDriverPtr driver, qemuDomainCleanupRemove(vm, qemuMigrationPrepareCleanup); VIR_FREE(priv->job.completed); + /* If migration used TLS, then command line creation generated a + * secinfo object and a TLS server object. Remove both now as this + * domain would now be a potential client of the next migration. */ + if (priv->migrateTLS) { + char *tlsAlias = qemuAliasTLSObjFromSrcAlias("migrate"); + char *secAlias = qemuDomainGetSecretAESAlias("migrate", false); + + qemuDomainDelTLSObjects(driver, vm, secAlias, tlsAlias); + qemuDomainSecretMigrateDestroy(&priv->migSecinfo); + VIR_FREE(tlsAlias); + priv->migrateTLS = false; + if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, + vm, driver->caps) < 0) + VIR_WARN("Failed to save migrateTLS on vm %s", vm->def->name); + } + cookie_flags = QEMU_MIGRATION_COOKIE_NETWORK | QEMU_MIGRATION_COOKIE_STATS | QEMU_MIGRATION_COOKIE_NBD; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 76f132b..b9d6a9d 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -5469,6 +5469,8 @@ qemuProcessLaunch(virConnectPtr conn, vm->def, priv->monConfig, priv->monJSON, priv->qemuCaps, incoming ? incoming->launchURI : NULL, + priv->migrateTLS, + priv->migSecinfo, snapshot, vmop, false, qemuCheckFips(), @@ -5901,6 +5903,8 @@ qemuProcessCreatePretendCmd(virConnectPtr conn, priv->monJSON, priv->qemuCaps, migrateURI, + false, + NULL, NULL, VIR_NETDEV_VPORT_PROFILE_OP_NO_OP, standalone, -- 2.9.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list