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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list