mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-20 07:59:00 +00:00
rpc: use new virt-ssh-helper binary for remote tunnelling
This wires up support for using the new virt-ssh-helper binary with the ssh, libssh and libssh2 protocols. The new binary will be used preferentially if it is available in $PATH, otherwise we fall back to traditional netcat. The "proxy" URI parameter can be used to force use of netcat e.g. qemu+ssh://host/system?proxy=netcat or the disable fallback e.g. qemu+ssh://host/system?proxy=native With use of virt-ssh-helper, we can now support remote session URIs qemu+ssh://host/session and this will only use virt-ssh-helper, with no fallback. This also lets the libvirtd process be auto-started, and connect directly to the modular daemons, avoiding use of virtproxyd back-compat tunnelling. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
6e4143c851
commit
f8ec7c842d
@ -259,6 +259,24 @@ Note that parameter values must be
|
||||
<td colspan="2"/>
|
||||
<td> Example: <code>mode=direct</code> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>proxy</code>
|
||||
</td>
|
||||
<td>auto, netcat, native </td>
|
||||
<td>
|
||||
<dl>
|
||||
<dt><code>auto</code></dt><dd>try native, fallback to netcat</dd>
|
||||
<dt><code>netcat</code></dt><dd>only use netcat</dd>
|
||||
<dt><code>native</code></dt><dd>only use native</dd>
|
||||
</dl>
|
||||
Can also be set in <code>libvirt.conf</code> as <code>remote_proxy</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"/>
|
||||
<td> Example: <code>proxy=native</code> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>command</code>
|
||||
@ -296,8 +314,10 @@ Note that parameter values must be
|
||||
<td> ssh, libssh2, libssh </td>
|
||||
<td>
|
||||
The name of the netcat command on the remote machine.
|
||||
The default is <code>nc</code>. For ssh transport, libvirt
|
||||
constructs an ssh command which looks like:
|
||||
The default is <code>nc</code>. This is not permitted
|
||||
when using the <code>native</code> proxy mode. For ssh
|
||||
transport, libvirt constructs an ssh command which looks
|
||||
like:
|
||||
|
||||
<pre><i>command</i> -p <i>port</i> [-l <i>username</i>] <i>hostname</i> <i>netcat</i> -U <i>socket</i>
|
||||
</pre>
|
||||
|
@ -761,6 +761,7 @@ doRemoteOpen(virConnectPtr conn,
|
||||
g_autofree char *knownHosts = NULL;
|
||||
g_autofree char *mode_str = NULL;
|
||||
g_autofree char *daemon_name = NULL;
|
||||
g_autofree char *proxy_str = NULL;
|
||||
bool sanity = true;
|
||||
bool verify = true;
|
||||
#ifndef WIN32
|
||||
@ -768,6 +769,7 @@ doRemoteOpen(virConnectPtr conn,
|
||||
#endif
|
||||
int mode;
|
||||
size_t i;
|
||||
int proxy;
|
||||
|
||||
if (inside_daemon && !conn->uri->server) {
|
||||
mode = REMOTE_DRIVER_MODE_DIRECT;
|
||||
@ -775,6 +777,14 @@ doRemoteOpen(virConnectPtr conn,
|
||||
mode = REMOTE_DRIVER_MODE_AUTO;
|
||||
}
|
||||
|
||||
/* Historically we didn't allow ssh tunnel with session mode,
|
||||
* since we can't construct the accurate path remotely,
|
||||
* so we can default to modern virt-ssh-helper */
|
||||
if (flags & VIR_DRV_OPEN_REMOTE_USER)
|
||||
proxy = VIR_NET_CLIENT_PROXY_NATIVE;
|
||||
else
|
||||
proxy = VIR_NET_CLIENT_PROXY_AUTO;
|
||||
|
||||
/* We handle *ALL* URIs here. The caller has rejected any
|
||||
* URIs we don't care about */
|
||||
|
||||
@ -812,6 +822,7 @@ doRemoteOpen(virConnectPtr conn,
|
||||
EXTRACT_URI_ARG_STR("known_hosts_verify", knownHostsVerify);
|
||||
EXTRACT_URI_ARG_STR("tls_priority", tls_priority);
|
||||
EXTRACT_URI_ARG_STR("mode", mode_str);
|
||||
EXTRACT_URI_ARG_STR("proxy", proxy_str);
|
||||
EXTRACT_URI_ARG_BOOL("no_sanity", sanity);
|
||||
EXTRACT_URI_ARG_BOOL("no_verify", verify);
|
||||
#ifndef WIN32
|
||||
@ -864,6 +875,17 @@ doRemoteOpen(virConnectPtr conn,
|
||||
(mode = remoteDriverModeTypeFromString(mode_str)) < 0)
|
||||
goto failed;
|
||||
|
||||
if (conf && !proxy_str &&
|
||||
virConfGetValueString(conf, "remote_proxy", &proxy_str) < 0)
|
||||
goto failed;
|
||||
|
||||
if (proxy_str &&
|
||||
(proxy = virNetClientProxyTypeFromString(proxy_str)) < 0) {
|
||||
virReportError(VIR_ERR_INVALID_ARG,
|
||||
_("Unnkown proxy type '%s'"), proxy_str);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* Sanity check that nothing requested !direct mode by mistake */
|
||||
if (inside_daemon && !conn->uri->server && mode != REMOTE_DRIVER_MODE_DIRECT) {
|
||||
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
||||
@ -948,8 +970,11 @@ doRemoteOpen(virConnectPtr conn,
|
||||
knownHosts,
|
||||
knownHostsVerify,
|
||||
sshauth,
|
||||
proxy,
|
||||
netcat,
|
||||
sockname,
|
||||
name,
|
||||
flags & VIR_DRV_OPEN_REMOTE_RO,
|
||||
auth,
|
||||
conn->uri);
|
||||
if (!priv->client)
|
||||
@ -969,8 +994,11 @@ doRemoteOpen(virConnectPtr conn,
|
||||
knownHosts,
|
||||
knownHostsVerify,
|
||||
sshauth,
|
||||
proxy,
|
||||
netcat,
|
||||
sockname,
|
||||
name,
|
||||
flags & VIR_DRV_OPEN_REMOTE_RO,
|
||||
auth,
|
||||
conn->uri);
|
||||
if (!priv->client)
|
||||
@ -1010,8 +1038,11 @@ doRemoteOpen(virConnectPtr conn,
|
||||
!tty,
|
||||
!verify,
|
||||
keyfile,
|
||||
proxy,
|
||||
netcat,
|
||||
sockname)))
|
||||
sockname,
|
||||
name,
|
||||
flags & VIR_DRV_OPEN_REMOTE_RO)))
|
||||
goto failed;
|
||||
|
||||
priv->is_secure = 1;
|
||||
|
@ -108,14 +108,6 @@ remoteGetUNIXSocketHelper(remoteDriverTransport transport,
|
||||
g_autofree char *userdir = NULL;
|
||||
|
||||
if (session) {
|
||||
if (transport != REMOTE_DRIVER_TRANSPORT_UNIX) {
|
||||
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
||||
_("Connecting to session instance without "
|
||||
"socket path is not supported by the %s "
|
||||
"transport"),
|
||||
remoteDriverTransportTypeToString(transport));
|
||||
return NULL;
|
||||
}
|
||||
userdir = virGetUserRuntimeDirectory();
|
||||
|
||||
sockname = g_strdup_printf("%s/%s-sock", userdir, sock_prefix);
|
||||
|
@ -50,6 +50,10 @@ enum {
|
||||
VIR_NET_CLIENT_MODE_COMPLETE,
|
||||
};
|
||||
|
||||
VIR_ENUM_IMPL(virNetClientProxy,
|
||||
VIR_NET_CLIENT_PROXY_LAST,
|
||||
"auto", "netcat", "native");
|
||||
|
||||
struct _virNetClientCall {
|
||||
int mode;
|
||||
|
||||
@ -414,23 +418,64 @@ virNetClientDoubleEscapeShell(const char *str)
|
||||
}
|
||||
|
||||
char *
|
||||
virNetClientSSHHelperCommand(const char *netcatPath,
|
||||
const char *socketPath)
|
||||
virNetClientSSHHelperCommand(virNetClientProxy proxy,
|
||||
const char *netcatPath,
|
||||
const char *socketPath,
|
||||
const char *driverURI,
|
||||
bool readonly)
|
||||
{
|
||||
g_autofree char *netcatPathSafe = virNetClientDoubleEscapeShell(netcatPath);
|
||||
g_autofree char *netcatPathSafe = virNetClientDoubleEscapeShell(netcatPath ? netcatPath : "nc");
|
||||
g_autofree char *driverURISafe = virNetClientDoubleEscapeShell(driverURI);
|
||||
g_autofree char *nccmd = NULL;
|
||||
g_autofree char *helpercmd = NULL;
|
||||
|
||||
if (!netcatPath)
|
||||
netcatPath = "nc";
|
||||
/* If user gave a 'netcat' path in the URI, we must
|
||||
* assume they want the legacy 'nc' based proxy, not
|
||||
* our new virt-ssh-helper
|
||||
*/
|
||||
if (proxy == VIR_NET_CLIENT_PROXY_AUTO &&
|
||||
netcatPath != NULL) {
|
||||
proxy = VIR_NET_CLIENT_PROXY_NETCAT;
|
||||
}
|
||||
|
||||
return g_strdup_printf(
|
||||
"sh -c "
|
||||
"'if '%s' -q 2>&1 | grep \"requires an argument\" >/dev/null 2>&1; then "
|
||||
"ARG=-q0;"
|
||||
nccmd = g_strdup_printf(
|
||||
"if '%s' -q 2>&1 | grep \"requires an argument\" >/dev/null 2>&1; then "
|
||||
"ARG=-q0;"
|
||||
"else "
|
||||
"ARG=;"
|
||||
"ARG=;"
|
||||
"fi;"
|
||||
"'%s' $ARG -U %s'",
|
||||
"'%s' $ARG -U %s",
|
||||
netcatPathSafe, netcatPathSafe, socketPath);
|
||||
|
||||
helpercmd = g_strdup_printf("virt-ssh-helper%s'%s'",
|
||||
readonly ? " -r " : " ",
|
||||
driverURISafe);
|
||||
|
||||
switch (proxy) {
|
||||
case VIR_NET_CLIENT_PROXY_AUTO:
|
||||
return g_strdup_printf("sh -c 'which virt-nc 1>/dev/null 2>&1; "
|
||||
"if test $? = 0; then "
|
||||
" %s; "
|
||||
"else"
|
||||
" %s; "
|
||||
"fi'", helpercmd, nccmd);
|
||||
|
||||
case VIR_NET_CLIENT_PROXY_NETCAT:
|
||||
return g_strdup_printf("sh -c '%s'", nccmd);
|
||||
|
||||
case VIR_NET_CLIENT_PROXY_NATIVE:
|
||||
if (netcatPath) {
|
||||
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
||||
_("netcat path not valid with native proxy mode"));
|
||||
return NULL;
|
||||
}
|
||||
return g_strdup_printf("sh -c '%s'", helpercmd);
|
||||
|
||||
case VIR_NET_CLIENT_PROXY_LAST:
|
||||
default:
|
||||
virReportEnumRangeError(virNetClientProxy, proxy);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -445,15 +490,18 @@ virNetClientPtr virNetClientNewSSH(const char *nodename,
|
||||
bool noTTY,
|
||||
bool noVerify,
|
||||
const char *keyfile,
|
||||
virNetClientProxy proxy,
|
||||
const char *netcatPath,
|
||||
const char *socketPath)
|
||||
const char *socketPath,
|
||||
const char *driverURI,
|
||||
bool readonly)
|
||||
{
|
||||
virNetSocketPtr sock;
|
||||
g_autofree char *command = NULL;
|
||||
|
||||
DEFAULT_VALUE(netcatPath, "nc");
|
||||
|
||||
command = virNetClientSSHHelperCommand(netcatPath, socketPath);
|
||||
if (!(command = virNetClientSSHHelperCommand(proxy, netcatPath, socketPath,
|
||||
driverURI, readonly)))
|
||||
return NULL;
|
||||
|
||||
if (virNetSocketNewConnectSSH(nodename, service, binary, username, noTTY,
|
||||
noVerify, keyfile, command, &sock) < 0)
|
||||
@ -470,8 +518,11 @@ virNetClientPtr virNetClientNewLibSSH2(const char *host,
|
||||
const char *knownHostsPath,
|
||||
const char *knownHostsVerify,
|
||||
const char *authMethods,
|
||||
virNetClientProxy proxy,
|
||||
const char *netcatPath,
|
||||
const char *socketPath,
|
||||
const char *driverURI,
|
||||
bool readonly,
|
||||
virConnectAuthPtr authPtr,
|
||||
virURIPtr uri)
|
||||
{
|
||||
@ -510,7 +561,9 @@ virNetClientPtr virNetClientNewLibSSH2(const char *host,
|
||||
DEFAULT_VALUE(username, "root");
|
||||
DEFAULT_VALUE(knownHostsVerify, "normal");
|
||||
|
||||
command = virNetClientSSHHelperCommand(netcatPath, socketPath);
|
||||
if (!(command = virNetClientSSHHelperCommand(proxy, netcatPath, socketPath,
|
||||
driverURI, readonly)))
|
||||
return NULL;
|
||||
|
||||
if (virNetSocketNewConnectLibSSH2(host, port,
|
||||
family,
|
||||
@ -530,8 +583,11 @@ virNetClientPtr virNetClientNewLibssh(const char *host,
|
||||
const char *knownHostsPath,
|
||||
const char *knownHostsVerify,
|
||||
const char *authMethods,
|
||||
virNetClientProxy proxy,
|
||||
const char *netcatPath,
|
||||
const char *socketPath,
|
||||
const char *driverURI,
|
||||
bool readonly,
|
||||
virConnectAuthPtr authPtr,
|
||||
virURIPtr uri)
|
||||
{
|
||||
@ -570,7 +626,9 @@ virNetClientPtr virNetClientNewLibssh(const char *host,
|
||||
DEFAULT_VALUE(username, "root");
|
||||
DEFAULT_VALUE(knownHostsVerify, "normal");
|
||||
|
||||
command = virNetClientSSHHelperCommand(netcatPath, socketPath);
|
||||
if (!(command = virNetClientSSHHelperCommand(proxy, netcatPath, socketPath,
|
||||
driverURI, readonly)))
|
||||
return NULL;
|
||||
|
||||
if (virNetSocketNewConnectLibssh(host, port,
|
||||
family,
|
||||
|
@ -30,9 +30,22 @@
|
||||
#include "virobject.h"
|
||||
#include "viruri.h"
|
||||
|
||||
typedef enum {
|
||||
VIR_NET_CLIENT_PROXY_AUTO,
|
||||
VIR_NET_CLIENT_PROXY_NETCAT,
|
||||
VIR_NET_CLIENT_PROXY_NATIVE,
|
||||
|
||||
VIR_NET_CLIENT_PROXY_LAST,
|
||||
} virNetClientProxy;
|
||||
|
||||
VIR_ENUM_DECL(virNetClientProxy);
|
||||
|
||||
char *
|
||||
virNetClientSSHHelperCommand(const char *netcatPath,
|
||||
const char *socketPath);
|
||||
virNetClientSSHHelperCommand(virNetClientProxy proxy,
|
||||
const char *netcatPath,
|
||||
const char *socketPath,
|
||||
const char *driverURI,
|
||||
bool readonly);
|
||||
|
||||
virNetClientPtr virNetClientNewUNIX(const char *path,
|
||||
bool spawnDaemon,
|
||||
@ -49,8 +62,11 @@ virNetClientPtr virNetClientNewSSH(const char *nodename,
|
||||
bool noTTY,
|
||||
bool noVerify,
|
||||
const char *keyfile,
|
||||
const char *netcat,
|
||||
const char *socketPath);
|
||||
virNetClientProxy proxy,
|
||||
const char *netcatPath,
|
||||
const char *socketPath,
|
||||
const char *driverURI,
|
||||
bool readonly);
|
||||
|
||||
virNetClientPtr virNetClientNewLibSSH2(const char *host,
|
||||
const char *port,
|
||||
@ -60,8 +76,11 @@ virNetClientPtr virNetClientNewLibSSH2(const char *host,
|
||||
const char *knownHostsPath,
|
||||
const char *knownHostsVerify,
|
||||
const char *authMethods,
|
||||
virNetClientProxy proxy,
|
||||
const char *netcatPath,
|
||||
const char *socketPath,
|
||||
const char *driverURI,
|
||||
bool readonly,
|
||||
virConnectAuthPtr authPtr,
|
||||
virURIPtr uri);
|
||||
|
||||
@ -73,8 +92,11 @@ virNetClientPtr virNetClientNewLibssh(const char *host,
|
||||
const char *knownHostsPath,
|
||||
const char *knownHostsVerify,
|
||||
const char *authMethods,
|
||||
virNetClientProxy proxy,
|
||||
const char *netcatPath,
|
||||
const char *socketPath,
|
||||
const char *driverURI,
|
||||
bool readonly,
|
||||
virConnectAuthPtr authPtr,
|
||||
virURIPtr uri);
|
||||
|
||||
|
@ -469,8 +469,11 @@ static int testSocketSSH(const void *opaque)
|
||||
virNetSocketPtr csock = NULL; /* Client socket */
|
||||
int ret = -1;
|
||||
char buf[1024];
|
||||
g_autofree char *command = virNetClientSSHHelperCommand(data->netcat,
|
||||
data->path);
|
||||
g_autofree char *command = virNetClientSSHHelperCommand(VIR_NET_CLIENT_PROXY_AUTO,
|
||||
data->netcat,
|
||||
data->path,
|
||||
"qemu:///session",
|
||||
true);
|
||||
|
||||
if (virNetSocketNewConnectSSH(data->nodename,
|
||||
data->service,
|
||||
|
Loading…
x
Reference in New Issue
Block a user