This patch allow libvirt-cim to use non-root's ssh key, not
using root's key to avoid exposing root's ssh login. Because libvirt-cim
runs in root mode so it is hard to satisfy some server security rules
especially about root's ssh key exposing. This is a walk around to improve
it.
This patch added three additonal paremeters in vs migration and migratable
method, they are DestinationHostParams, SSH_Key_Src, SSH_Key_Dest.
DestinationHostParams is the addtional string which would be appended after
the uri if it was set, so with this parameter user could add additional
parameter in libvirt remote uri, such as "?keyfile=/tmp/tempkey.rsa". Because
libvirt woulkd ignore the private key file parameter, if the key's directory
was not owned by the user, and libvirt-cim runs as root, so SSH_Key_Src and
SSH_Key_Dest were provided to allow a copying of keyfile to a directory that
owned by root, at runtime. if SSH_Key_Src and SSH_Key_Dest were set,
libvirt-cim would run shell command "cp -f [SSH_Key_Src] [SSH_Key_Dest]".
Typically cim client with authority to do a migration, could specify these
three additonal parameters with ssh migration method set, as
DestinationHostParams="?keyfile=/root/temp_migration_key.rsa"
SSH_Key_Src="/home/VController/.ssh/id_rsa"
SSH_Key_Dest="/root/temp_migration_key.rsa"
then, the migration would complete with VController's key pairs, instead of
root's, avoided turning on root's ssh logins.
Test was done when SELinux was shutdown.
V2:
Better documentation.
Signed-off-by: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
---
src/Virt_VSMigrationService.c | 96 +++++++++++++++++++++++++++++++++++++++--
1 files changed, 92 insertions(+), 4 deletions(-)
diff --git a/src/Virt_VSMigrationService.c b/src/Virt_VSMigrationService.c
index 76e3d25..55442ee 100644
--- a/src/Virt_VSMigrationService.c
+++ b/src/Virt_VSMigrationService.c
@@ -150,6 +150,7 @@ static CMPIStatus get_migration_uri(CMPIInstance *msd,
static char *dest_uri(const char *cn,
const char *dest,
+ const char *dest_params,
uint16_t transport)
{
const char *prefix;
@@ -157,6 +158,7 @@ static char *dest_uri(const char *cn,
const char *param = "";
char *uri = NULL;
int rc;
+ int param_labeled = 0;
if (STARTS_WITH(cn, "Xen"))
prefix = "xen";
@@ -197,16 +199,75 @@ static char *dest_uri(const char *cn,
goto out;
}
- if (!STREQC(param, ""))
+ if (!STREQC(param, "")) {
rc = asprintf(&uri, "%s/%s", uri, param);
+ param_labeled = 1;
+ }
- if (rc == -1)
+ if (rc == -1) {
uri = NULL;
+ goto out;
+ }
+ if (dest_params) {
+ if (param_labeled == 0) {
+ rc = asprintf(&uri, "%s?%s", uri, dest_params);
+ } else {
+ rc = asprintf(&uri, "%s%s", uri, dest_params);
+ }
+ if (rc == -1) {
+ uri = NULL;
+ goto out;
+ }
+ }
out:
return uri;
}
+/* libvirt need private key specified must be placed in a directory owned by
+ root, because libvirt-cim now runs as root. So here the key would be copied,
+ up layer need to delete that key after migration. This method could allow
+ libvirt-cim borrow a non-root ssh private key, instead of using root's private
+ key, avoid security risk. */
+static int ssh_key_cp(const char *src, const char *dest)
+{
+ char *cmd = NULL;
+ int rc;
+ int ret = 0;
+ FILE *stream = NULL;
+ char buf[256];
+
+ rc = asprintf(&cmd, "cp -f %s %s", src, dest);
+ if (rc == -1) {
+ cmd = NULL;
+ ret = -1;
+ goto out;
+ }
+
+ CU_DEBUG("excuting system cmd [%s].", cmd);
+ stream = popen(cmd, "r");
+ if (stream == NULL) {
+ CU_DEBUG("Failed to open pipe to run command");
+ ret = -2;
+ goto out;
+ }
+ usleep(10000);
+
+ buf[255] = 0;
+ while (fgets(buf, sizeof(buf), stream) != NULL) {
+ CU_DEBUG("Exception got: %s.", buf);
+ ret = -3;
+ goto out;
+ }
+
+ out:
+ if (stream != NULL) {
+ pclose(stream);
+ }
+ free(cmd);
+ return ret;
+}
+
static CMPIStatus get_msd_values(const CMPIObjectPath *ref,
const char *destination,
const CMPIArgs *argsin,
@@ -217,6 +278,14 @@ static CMPIStatus get_msd_values(const CMPIObjectPath *ref,
CMPIInstance *msd;
uint16_t uri_type;
char *uri = NULL;
+ const char *dest_params = NULL;
+ const char *ssh_hack_src = NULL;
+ const char *ssh_hack_dest = NULL;
+ int ret;
+
+ cu_get_str_arg(argsin, "DestinationHostParams", &dest_params);
+ cu_get_str_arg(argsin, "SSH_Key_Src", &ssh_hack_src);
+ cu_get_str_arg(argsin, "SSH_Key_Dest", &ssh_hack_dest);
s = get_msd(ref, argsin, &msd);
if (s.rc != CMPI_RC_OK)
@@ -230,7 +299,7 @@ static CMPIStatus get_msd_values(const CMPIObjectPath *ref,
if (s.rc != CMPI_RC_OK)
goto out;
- uri = dest_uri(CLASSNAME(ref), destination, uri_type);
+ uri = dest_uri(CLASSNAME(ref), destination, dest_params, uri_type);
if (uri == NULL) {
cu_statusf(_BROKER, &s,
CMPI_RC_ERR_FAILED,
@@ -238,6 +307,19 @@ static CMPIStatus get_msd_values(const CMPIObjectPath *ref,
goto out;
}
+ if ((ssh_hack_src) && (ssh_hack_dest)) {
+ CU_DEBUG("hacking ssh keys src %s, dest %s.",
+ ssh_hack_src, ssh_hack_dest);
+ ret = ssh_key_cp(ssh_hack_src, ssh_hack_dest);
+ if (ret < 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to copy ssh key files");
+ goto out;
+ }
+ }
+
+ CU_DEBUG("Migrate tring to connect remote host with uri %s.", uri);
*conn = virConnectOpen(uri);
if (*conn == NULL) {
CU_DEBUG("Failed to connect to remote host (%s)", uri);
@@ -1537,7 +1619,7 @@ static CMPIStatus migrate_vs_host(CMPIMethodMI *self,
const char *dhost = NULL;
CMPIObjectPath *system;
const char *name = NULL;
-
+
cu_get_str_arg(argsin, "DestinationHost", &dhost);
cu_get_ref_arg(argsin, "ComputerSystem", &system);
@@ -1608,6 +1690,9 @@ static struct method_handler vsimth = {
.handler = vs_migratable_host,
.args = {{"ComputerSystem", CMPI_ref, false},
{"DestinationHost", CMPI_string, false},
+ {"DestinationHostParams", CMPI_string, true},
+ {"SSH_Key_Src", CMPI_string, true},
+ {"SSH_Key_Dest", CMPI_string, true},
{"MigrationSettingData", CMPI_instance, true},
{"NewSystemSettingData", CMPI_instance, true},
{"NewResourceSettingData", CMPI_instanceA, true},
@@ -1632,6 +1717,9 @@ static struct method_handler mvsth = {
.handler = migrate_vs_host,
.args = {{"ComputerSystem", CMPI_ref, false},
{"DestinationHost", CMPI_string, false},
+ {"DestinationHostParams", CMPI_string, true},
+ {"SSH_Key_Src", CMPI_string, true},
+ {"SSH_Key_Dest", CMPI_string, true},
{"MigrationSettingData", CMPI_instance, true},
{"NewSystemSettingData", CMPI_instance, true},
{"NewResourceSettingData", CMPI_instanceA, true},
--
1.7.1