From Fedora-18 there has been some noticeable changes to polkit. Policy kit helps access to certain privileged process to unprivileged applications or users in this case. I generally use systems with SELinux Enabled and also confine my users. Since most of my job requires testing various applications , I keep creating a lot of vm’s (RHEL5,RHEL6). For this virt-manager is my preferred application.
Recently i have been assigned with a new Intel Hardware which has hardware Virtualization enabled with 1TB Hard disk. So installed Fedora-18 to create VM’s. My requirement is i should be able to install vm’s using Non-root user and that too with user who’s confined.
- Create a user
$ useradd test
- Map this user to staff_u selinux user
$ semanage login -a -s staff_u test Login Name SELinux User MLS/MCS Range Service __default__ user_u s0 * ceres sysadm_u s0-s0:c0.c1023 * juno staff_u s0 * root root s0-s0:c0.c1023 * system_u system_u s0-s0:c0.c1023 * test staff_u s0-s0:c0.c1023 *
- login as test user and connect to libvirt socket using virsh
[mniranja@mniranja mar20]$ ssh test@10.65.201.167 test@10.65.201.167's password: Last login: Wed Mar 20 00:20:13 2013 from localhost [test@dhcp201-167 ~]$ id -Z staff_u:staff_r:staff_t:s0-s0:c0.c1023
- Connect to libvirt socket
[test@dhcp201-167 ~]$ virsh -c qemu:///system error: authentication failed: Authorization requires authentication but no agent is available. error: failed to connect to the hypervisor
As you can see above it doesn’t allow to connect , In earlier versions of Fedora, you could use policy kit to create a authorization rule to connect to libvirt socket. Refer Libvirt documentation. This method is also called Policy Kit LocalAuthority. So on Fedora-16 system i had the following rule
[root@reserved 50-local.d]# cat 50-org.example-libvirt-remote-access.pkla
[Remote libvirt SSH access]
Identity=unix-group:virt
Action=org.libvirt.unix.manage;org.libvirt.unix.monitor
ResultAny=yes
ResultInactive=yes
ResultActive=yes
The above would allow users of group “virt” to access libvirt and manage libvirt through policy kit action “org.libvirt.unix.manage” . The above rules are placed in file 50-org.example-libvirt-remote-access.pkla under directory “/etc/polkit-1/localauthority/50-local.d”.
I hoped the same would work on Fedora-18 but it doesn’t as Policy kit localAuthority has been removed totally, instead all the custom policy kit rules should be placed under /etc/polkit-1/rules.d/ directory. Syntax of writing rules has been changed and Java Script syntax need to be used. Refer DavidZ blog for more information regarding the change.
On Fedora-18 i managed to do the same by adding the following rule file 10.virt.rules created under /etc/polkit-1/rules.d directory
[root@dhcp201-167 rules.d]# cat 10.virt.rules
polkit.addRule(function(action, subject) {
polkit.log("action=" + action);
polkit.log("subject=" + subject);
var now = new Date();
polkit.log("now=" + now)
if ((action.id == "org.libvirt.unix.manage" || action.id == "org.libvirt.unix.monitor") && subject.isInGroup("virt")) {
return polkit.Result.YES;
}
return null;
});
Thanks To Gilbert , As you can see the above allows polkit action “libvirt.unix.manage” || “org.libvirt.unix.monitor” to all the users of group “virt”
- Restart polkit service
$ systemctl restart polkit.service
- Add the user test to group virt
$ usermod -aG virt test
- login as test user and connect to libvirt using virsh
[test@dhcp201-167 ~]$ id -Z staff_u:staff_r:staff_t:s0-s0:c0.c1023 [test@dhcp201-167 ~]$ id uid=1002(test) gid=1003(test) groups=1003(test),1001(virt) context=staff_u:staff_r:staff_t:s0-s0:c0.c1023 [test@dhcp201-167 ~]$ virsh -c qemu:///system Welcome to virsh, the virtualization interactive terminal. Type: 'help' for help with commands 'quit' to quit
- Check the logs using journalctl
[root@dhcp201-167 ~]# journalctl -xn -- Logs begin at Tue 2013-03-19 22:54:05 EDT, end at Wed 2013-03-20 00:43:25 EDT. -- Mar 20 00:43:02 dhcp201-167.englab.pnq.redhat.com kernel: usb 1-1.3: Product: USB Optical Mouse Mar 20 00:43:02 dhcp201-167.englab.pnq.redhat.com kernel: usb 1-1.3: Manufacturer: PixArt Mar 20 00:43:02 dhcp201-167.englab.pnq.redhat.com kernel: input: PixArt USB Optical Mouse as /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.3/1-1.3:1.0/input/in Mar 20 00:43:02 dhcp201-167.englab.pnq.redhat.com kernel: hid-generic 0003:0461:4E22.006D: input,hidraw0: USB HID v1.11 Mouse [PixArt USB Optical Mouse] on usb Mar 20 00:43:18 dhcp201-167.englab.pnq.redhat.com sshd[3722]: Accepted password for test from 10.3.235.177 port 53789 ssh2 Mar 20 00:43:18 dhcp201-167.englab.pnq.redhat.com systemd-logind[596]: New session 18 of user test. -- Subject: A new session 18 has been created for user test -- Defined-By: systemd -- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel -- Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat -- Documentation: http://www.freedesktop.org/wiki/Software/systemd/catalog/8d45620c1a4348dbb17410da57c60c66 -- -- A new session with the ID 18 has been created for the user test. -- -- The leading process of the session is 3722. Mar 20 00:43:18 dhcp201-167.englab.pnq.redhat.com sshd[3722]: pam_unix(sshd:session): session opened for user test by (uid=0) Mar 20 00:43:25 dhcp201-167.englab.pnq.redhat.com polkitd[1688]: /etc/polkit-1/rules.d/10.virt.rules:2: action=[Action id='org.libvirt.unix.manage'] Mar 20 00:43:25 dhcp201-167.englab.pnq.redhat.com polkitd[1688]: /etc/polkit-1/rules.d/10.virt.rules:3: subject=[Subject pid=3791 user='test' groups=test,virt, Mar 20 00:43:25 dhcp201-167.englab.pnq.redhat.com polkitd[1688]: /etc/polkit-1/rules.d/10.virt.rules:5: now=Wed Mar 20 2013 00:43:25 GMT-0400 (EDT)
Alessandro said:
Thank you very much… that’s at least 5 days that I’m struggling with my Fedora 19… I did an upgrade from Fedora 16->17->18->19 in one day, and some things were not working anymore, and with your blog I could find a way out!!! Thank you very very very very very very much!!!!
niranjanmr said:
I am happy that this article helped you.
niranjanmr said:
Greetings, My earlier policy kit rule had an error which other’s had commented, Could you check the post again to get the modified policy kit rule for allowing non-root users to access libvirt.
Please view other comments, for more information.
Dave Gilbert said:
Please mod that example to:
usermod -aG virt test
without the -a usermod deletes you from all other groups – .e.g wheel so sudo doesn’t work, so when you’re doing it on your real user it’s a mess!
Dave Gilbert said:
Another question, you use the line:
if (action.id == “org.libvirt.unix.manage” || “org.libvirt.unix.monitor” && subject.isInGroup(“virt”)) {
is that right? I would have expected:
if ((action.id == “org.libvirt.unix.manage” || action.id == “org.libvirt.unix.monitor”) && subject.isInGroup(“virt”)) {
?
niranjanmr said:
Greetings,
Thanks for the comment, I am not exactly sure your change should also work, do you see any disadvantage with my if condition. ?
Dave Gilbert said:
I think your if condition is returning polkit.Result.YES for entirely unrelated polkit queries; for example I think it’s letting me mount a disk partition without password
Kevin Kofler said:
Your if condition as written just plain does not work. It’s just the permissiveness of JavaScript which does not make it trigger an outright error.
Real-world programming languages do not understand the natural-language syntax a == “foo” || “bar”. You have to write a == “foo” || a == “bar”.
For JavaScript, the “org.libvirt.unix.monitor” string you use in a boolean context without comparing it to anything is always true. In addition, && has higher priority than || (in pretty much all C-style languages, and that includes JavaScript, as well as C++, Java etc.). So your condition:
if (action.id == “org.libvirt.unix.manage” || “org.libvirt.unix.monitor” && subject.isInGroup(“virt”)) {
is interpreted as:
if (action.id == “org.libvirt.unix.manage” || (“org.libvirt.unix.monitor” && subject.isInGroup(“virt”))) {
which means:
if (action.id == “org.libvirt.unix.manage” || (true && subject.isInGroup(“virt”))) {
which simplifies to:
if (action.id == “org.libvirt.unix.manage” || subject.isInGroup(“virt”)) {
which is clearly NOT what you mean at all.
Please change it to Dave Gilbert’s version, which is almost certainly what you actually meant when you wrote that line.
And sorry, but I think you should really try to understand JavaScript before posting HOWTOs with JavaScript code in them.
niranjanmr said:
Thanks Kevin & Gilbert for the comments , I have corrected my mistake, Next i will be more careful before writing any HowTo.
Kevin Kofler said:
Sorry, but your code is still wrong.
action.id == “org.libvirt.unix.manage” || “org.libvirt.unix.monitor”
should be:
action.id == “org.libvirt.unix.manage” || action.id == “org.libvirt.unix.monitor”
Again, x == “foo” || “bar” is not valid programming language syntax, you have to say x == “foo” || x == “bar” explicitly.
niranjanmr said:
I have fixed it now.
Pingback: Get rid of password prompt for Vagrant commands on Libvirt | Blog of Lalatendu Mohanty