https://bugzilla.redhat.com/show_bug.cgi?id=872166
When the login session doesn't have an ssh -X type display agent in
order for libvirtd to run the polkit session authentication, attempts
to run 'virsh -c qemu:///system list' from an unauthorized user (or one
that isn't part of the libvirt /etc/group) will fail with the following
error from libvirtd:
error: authentication failed: no agent is available to authenticate -
polkit agent 'org.libvirt.unix.manage' is not available
In order to handle the local authentication, add a new switch "--pkauth"
to virsh which will make use of the virPolkitAgent* API's in order to
handle the text authentication when not a readonly request.
With this patch in place, the following occurs:
$ virsh --pkauth -c qemu:///system list
==== AUTHENTICATING FOR org.libvirt.unix.manage ===
System policy prevents management of local virtualized systems
Authenticating as: Some User (SUser)
Password:
==== AUTHENTICATION COMPLETE ===
Id Name State
----------------------------------------------------
1 somedomain running
$
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
tools/virsh.c | 22 +++++++++++++++++++---
tools/virsh.h | 2 ++
tools/virsh.pod | 10 ++++++++++
tools/vsh.h | 1 +
4 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index b96dbda..83cebe0 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -143,6 +143,7 @@ virshConnect(vshControl *ctl, const char *uri, bool readonly)
int interval = 5; /* Default */
int count = 6; /* Default */
bool keepalive_forced = false;
+ virCommandPtr pkagent = NULL;
if (ctl->keepalive_interval >= 0) {
interval = ctl->keepalive_interval;
@@ -153,10 +154,17 @@ virshConnect(vshControl *ctl, const char *uri, bool readonly)
keepalive_forced = true;
}
+ if (!readonly && ctl->pkauth) {
+ if (!(pkagent = virPolkitAgentCreate()))
+ return NULL;
+ if (virPolkitAgentCheck() < 0)
+ goto cleanup;
+ }
+
c = virConnectOpenAuth(uri, virConnectAuthPtrDefault,
readonly ? VIR_CONNECT_RO : 0);
if (!c)
- return NULL;
+ goto cleanup;
if (interval > 0 &&
virConnectSetKeepAlive(c, interval, count) != 0) {
@@ -165,12 +173,15 @@ virshConnect(vshControl *ctl, const char *uri, bool readonly)
_("Cannot setup keepalive on connection "
"as requested, disconnecting"));
virConnectClose(c);
- return NULL;
+ c = NULL;
+ goto cleanup;
}
vshDebug(ctl, VSH_ERR_INFO, "%s",
_("Failed to setup keepalive on connection\n"));
}
+ cleanup:
+ virPolkitAgentDestroy(pkagent);
return c;
}
@@ -490,6 +501,7 @@ virshUsage(void)
" -K | --keepalive-count=NUM\n"
" number of possible missed
keepalive messages\n"
" -l | --log=FILE output logging to file\n"
+ " -p | --pkauth start background polkit text
authentication agent\n"
" -q | --quiet quiet mode\n"
" -r | --readonly connect readonly\n"
" -t | --timing print timing information\n"
@@ -701,13 +713,14 @@ virshParseArgv(vshControl *ctl, int argc, char **argv)
{"readonly", no_argument, NULL, 'r'},
{"timing", no_argument, NULL, 't'},
{"version", optional_argument, NULL, 'v'},
+ {"pkauth", no_argument, NULL, 'p'},
{NULL, 0, NULL, 0}
};
/* Standard (non-command) options. The leading + ensures that no
* argument reordering takes place, so that command options are
* not confused with top-level virsh options. */
- while ((arg = getopt_long(argc, argv, "+:c:d:e:hk:K:l:qrtvV", opt,
&longindex)) != -1) {
+ while ((arg = getopt_long(argc, argv, "+:c:d:e:hk:K:l:pqrtvV", opt,
&longindex)) != -1) {
switch (arg) {
case 'c':
VIR_FREE(ctl->connname);
@@ -779,6 +792,9 @@ virshParseArgv(vshControl *ctl, int argc, char **argv)
ctl->logfile = vshStrdup(ctl, optarg);
vshOpenLogFile(ctl);
break;
+ case 'p':
+ ctl->pkauth = true;
+ break;
case 'q':
ctl->quiet = true;
break;
diff --git a/tools/virsh.h b/tools/virsh.h
index 8b5e5ba..a6c7289 100644
--- a/tools/virsh.h
+++ b/tools/virsh.h
@@ -36,6 +36,8 @@
# include "internal.h"
# include "virerror.h"
# include "virthread.h"
+# include "vircommand.h"
+# include "virpolkit.h"
# include "vsh.h"
# define VIRSH_PROMPT_RW "virsh # "
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 435c649..5368de7 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -90,6 +90,16 @@ no effect to this setting in case the I<INTERVAL> is set to 0.
Output logging details to I<FILE>.
+=item B<-p>, B<--pkauth>
+
+Start a local Polkit Authentication Agent in order to authenticate an
+unprivileged user for write access from a text session that cannot
+autolaunch a graphical Polkit Agent. Using this mechanism is an
+alternative to adding the user to the libvirt group list in /etc/group.
+The authentication processing requires the ability to view stdout and
+read from stdin. If Polkit is not available on the host, then the
+command will fail.
+
=item B<-q>, B<--quiet>
Avoid extra informational messages.
diff --git a/tools/vsh.h b/tools/vsh.h
index 0c5abdc..151fdcc 100644
--- a/tools/vsh.h
+++ b/tools/vsh.h
@@ -202,6 +202,7 @@ struct _vshControl {
vshCmd *cmd; /* the current command */
char *cmdstr; /* string with command */
bool imode; /* interactive mode? */
+ bool pkauth; /* start polkit authentication agent */
bool quiet; /* quiet mode */
bool timing; /* print timing info? */
int debug; /* print debug messages? */
--
2.5.0