For encrypted migration of VMs, QEMU provides the TLS-PSK authentication apart from TLS certificates. This mechanism relies on pre-shared keys (a secret key that is known to both sender and receiver prior to secure communication) for providing secure transfer of data. We store these keys in a pre-shared key file, where each line contains a pair of identifier and its corresponding key. During an encrypted migration, the parties negotiate which unique identifier to utilize, then parse the key file to extract the key matching the identifier.
Add the "migrate_tls_psk_dir" parameter to qemu.conf to allow users to define the path containing the pre-shared keys. In case the user does not define this parameter and attempts to utilize TLS-PSK for migration, we fallback to the configurable "default_tls_psk_dir" parameter whose value is set to /etc/pki/qemu-psk by default. In addition, we get the client identity by parsing the migration URI, defaulting to 'qemu' if username is undefined. Example entry format in a PSK file: qemu:61aa7b2c93d4e8f10c25b6a782e3f4051a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d Suggested-by: Tejus GK <[email protected]> Signed-off-by: Abhisek Panda <[email protected]> --- src/qemu/libvirtd_qemu.aug | 2 ++ src/qemu/qemu.conf.in | 19 +++++++++++ src/qemu/qemu_conf.c | 55 +++++++++++++++++++++++++++++- src/qemu/qemu_conf.h | 3 ++ src/qemu/qemu_migration.c | 2 ++ src/qemu/test_libvirtd_qemu.aug.in | 2 ++ tests/testutilsqemu.c | 2 ++ 7 files changed, 84 insertions(+), 1 deletion(-) diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug index eb790d48be..75639919fa 100644 --- a/src/qemu/libvirtd_qemu.aug +++ b/src/qemu/libvirtd_qemu.aug @@ -29,6 +29,7 @@ module Libvirtd_qemu = (* Config entry grouped by function - same order as example config *) let default_tls_entry = str_entry "default_tls_x509_cert_dir" | bool_entry "default_tls_x509_verify" + | str_entry "default_tls_psk_dir" | str_entry "default_tls_x509_secret_uuid" | str_entry "default_tls_priority" @@ -68,6 +69,7 @@ module Libvirtd_qemu = | str_entry "migrate_tls_x509_secret_uuid" | str_entry "migrate_tls_priority" | bool_entry "migrate_tls_force" + | str_entry "migrate_tls_psk_dir" let backup_entry = str_entry "backup_tls_x509_cert_dir" | bool_entry "backup_tls_x509_verify" diff --git a/src/qemu/qemu.conf.in b/src/qemu/qemu.conf.in index 5eacd70022..5dfd3229e5 100644 --- a/src/qemu/qemu.conf.in +++ b/src/qemu/qemu.conf.in @@ -49,6 +49,17 @@ #default_tls_x509_verify = 1 +# Use of TLS-PSK requires the pre-shared key files to be present. +# The default is to keep them in /etc/pki/qemu-psk. This directory must contain +# keys.psk - PSK key information +# +# If the directory does not exist, libvirtd will fail to start. If the +# directory doesn't contain the necessary files, VM migration will fail +# during TLS handshake if they are configured to use TLS-PSK. +# +#default_tls_psk_dir = "/etc/pki/qemu-psk" + + # Libvirt assumes the server-key.pem file is unencrypted by default. # To use an encrypted server-key.pem file, the password to decrypt # the PEM file is required. This can be provided by creating a secret @@ -437,6 +448,14 @@ #migrate_tls_force = 0 +# In order to override the default TLS pre-shared key files location for migration, +# supply a valid path to the key files. If the provided path does not exist, libvirtd +# will fail to start. If the path is not provided, but TLS-PSK-based migration is +# requested, then the default_tls_psk_dir path will be used. +# +#migrate_tls_psk_dir = "/etc/pki/libvirt-migrate-psk" + + # In order to override the default TLS certificate location for backup NBD # server certificates, supply a valid path to the certificate directory. If the # provided path does not exist, libvirtd will fail to start. If the path is diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 9c32310096..f52c8d78dd 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -245,14 +245,16 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged, cfg->passtStateDir = g_strdup_printf("%s/passt", cfg->stateDir); cfg->dbusStateDir = g_strdup_printf("%s/dbus", cfg->stateDir); - /* Set the default directory to find TLS X.509 certificates. + /* Set the default directory to find TLS X.509 certificates and pre-shared key files. * This will then be used as a fallback if the service specific * directory doesn't exist (although we don't check if this exists). */ if (root == NULL) { cfg->defaultTLSx509certdir = g_strdup(SYSCONFDIR "/pki/qemu"); + cfg->defaultTLSPSKdir = g_strdup(SYSCONFDIR "/pki/qemu-psk"); } else { cfg->defaultTLSx509certdir = g_strdup_printf("%s/etc/pki/qemu", root); + cfg->defaultTLSPSKdir = g_strdup_printf("%s/etc/pki/qemu-psk", root); } cfg->vncListen = g_strdup(VIR_LOOPBACK_IPV4_ADDR); @@ -380,6 +382,7 @@ static void virQEMUDriverConfigDispose(void *obj) g_free(cfg->defaultTLSx509certdir); g_free(cfg->defaultTLSx509secretUUID); + g_free(cfg->defaultTLSPSKdir); g_free(cfg->vncTLSx509certdir); g_free(cfg->vncTLSx509secretUUID); @@ -406,6 +409,8 @@ static void virQEMUDriverConfigDispose(void *obj) g_free(cfg->migrateTLSx509certdir); g_free(cfg->migrateTLSx509secretUUID); + g_free(cfg->migrateTLSPSKdir); + g_free(cfg->backupTLSx509certdir); g_free(cfg->backupTLSx509secretUUID); @@ -472,6 +477,9 @@ virQEMUDriverConfigLoadDefaultTLSEntry(virQEMUDriverConfig *cfg, if (virConfGetValueString(conf, "default_tls_priority", &cfg->defaultTLSpriority) < 0) return -1; + if ((rv = virConfGetValueString(conf, "default_tls_psk_dir", &cfg->defaultTLSPSKdir)) < 0) + return -1; + cfg->defaultTLSPSKdirPresent = (rv == 1); return 0; } @@ -611,6 +619,11 @@ virQEMUDriverConfigLoadSpecificTLSEntry(virQEMUDriverConfig *cfg, #undef GET_CONFIG_TLS_CERTINFO_COMMON #undef GET_CONFIG_TLS_CERTINFO_SERVER + + if (virConfGetValueString(conf, "migrate_tls_psk_dir", + &cfg->migrateTLSPSKdir) < 0) + return -1; + return 0; } @@ -1445,6 +1458,15 @@ virQEMUDriverConfigValidate(virQEMUDriverConfig *cfg) } } + if (cfg->defaultTLSPSKdirPresent) { + if (!virFileExists(cfg->defaultTLSPSKdir)) { + virReportError(VIR_ERR_CONF_SYNTAX, + _("default_tls_psk_dir directory '%1$s' does not exist"), + cfg->defaultTLSPSKdir); + return -1; + } + } + if (cfg->vncTLSx509certdir && !virFileExists(cfg->vncTLSx509certdir)) { virReportError(VIR_ERR_CONF_SYNTAX, @@ -1485,6 +1507,14 @@ virQEMUDriverConfigValidate(virQEMUDriverConfig *cfg) return -1; } + if (cfg->migrateTLSPSKdir && + !virFileExists(cfg->migrateTLSPSKdir)) { + virReportError(VIR_ERR_CONF_SYNTAX, + _("migrate_tls_psk_dir directory '%1$s' does not exist"), + cfg->migrateTLSPSKdir); + return -1; + } + if (cfg->backupTLSx509certdir && !virFileExists(cfg->backupTLSx509certdir)) { virReportError(VIR_ERR_CONF_SYNTAX, @@ -1586,6 +1616,29 @@ virQEMUDriverConfigSetDefaults(virQEMUDriverConfig *cfg) #undef SET_TLS_VERIFY_DEFAULT + + /* + * If a "SYSCONFDIR" + "pki/libvirt-<val>-psk" exists, then assume someone + * has created a val specific area to place service specific key files. + * + * If the service specific directory doesn't exist, 'assume' that the + * user has created and populated the "SYSCONFDIR" + "pki/libvirt-default-psk". + */ +#define SET_TLS_PSK_DEFAULT(val) \ + do { \ + if (cfg->val ## TLSPSKdir) \ + break; \ + if (virFileExists(SYSCONFDIR "/pki/libvirt-"#val"-psk")) { \ + cfg->val ## TLSPSKdir = g_strdup(SYSCONFDIR "/pki/libvirt-"#val"-psk"); \ + } else { \ + cfg->val ## TLSPSKdir = g_strdup(cfg->defaultTLSPSKdir); \ + } \ + } while (0) + + SET_TLS_PSK_DEFAULT(migrate); + + #undef SET_TLS_PSK_DEFAULT + return 0; } diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index 511ab77f71..ba7364dc89 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -130,6 +130,8 @@ struct _virQEMUDriverConfig { bool defaultTLSx509verifyPresent; char *defaultTLSx509secretUUID; char *defaultTLSpriority; + char *defaultTLSPSKdir; + bool defaultTLSPSKdirPresent; bool vncAutoUnixSocket; bool vncTLS; @@ -169,6 +171,7 @@ struct _virQEMUDriverConfig { char *migrateTLSx509secretUUID; char *migrateTLSpriority; bool migrateTLSForce; + char *migrateTLSPSKdir; char *backupTLSx509certdir; bool backupTLSx509verify; diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 4a43ab83b0..af981fb992 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -4355,6 +4355,7 @@ struct _qemuMigrationSpec { const char *protocol; const char *name; int port; + const char *username; } host; struct { @@ -5460,6 +5461,7 @@ qemuMigrationSrcPerformNative(virQEMUDriver *driver, spec.dest.host.protocol = uribits->scheme; spec.dest.host.name = uribits->server; spec.dest.host.port = uribits->port; + spec.dest.host.username = uribits->user; } spec.fwdType = MIGRATION_FWD_DIRECT; diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in index 2582c6a09c..9782e45b59 100644 --- a/src/qemu/test_libvirtd_qemu.aug.in +++ b/src/qemu/test_libvirtd_qemu.aug.in @@ -4,6 +4,7 @@ module Test_libvirtd_qemu = test Libvirtd_qemu.lns get conf = { "default_tls_x509_cert_dir" = "/etc/pki/qemu" } { "default_tls_x509_verify" = "1" } +{ "default_tls_psk_dir" = "/etc/pki/qemu-psk" } { "default_tls_x509_secret_uuid" = "00000000-0000-0000-0000-000000000000" } { "default_tls_priority" = "@SYSTEM" } { "vnc_listen" = "0.0.0.0" } @@ -45,6 +46,7 @@ module Test_libvirtd_qemu = { "migrate_tls_x509_secret_uuid" = "00000000-0000-0000-0000-000000000000" } { "migrate_tls_priority" = "@SYSTEM" } { "migrate_tls_force" = "0" } +{ "migrate_tls_psk_dir" = "/etc/pki/libvirt-migrate-psk" } { "backup_tls_x509_cert_dir" = "/etc/pki/libvirt-backup" } { "backup_tls_x509_verify" = "1" } { "backup_tls_x509_secret_uuid" = "00000000-0000-0000-0000-000000000000" } diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c index e7a61d0c6f..6c71272e80 100644 --- a/tests/testutilsqemu.c +++ b/tests/testutilsqemu.c @@ -401,6 +401,8 @@ int qemuTestDriverInit(virQEMUDriver *driver) cfg->nbdTLSx509certdir = g_strdup("/etc/pki/libvirt-nbd"); VIR_FREE(cfg->migrateTLSx509certdir); cfg->migrateTLSx509certdir = g_strdup("/etc/pki/libvirt-migrate"); + VIR_FREE(cfg->migrateTLSPSKdir); + cfg->migrateTLSPSKdir = g_strdup("/etc/pki/libvirt-migrate-psk"); VIR_FREE(cfg->backupTLSx509certdir); cfg->backupTLSx509certdir = g_strdup("/etc/pki/libvirt-backup"); -- 2.39.3
