Bug 1741428

Summary: Destroy network use polkit access control failed as access denied
Product: Red Hat Enterprise Linux Advanced Virtualization Reporter: yalzhang <yalzhang>
Component: libvirtAssignee: Laine Stump <laine>
Status: CLOSED ERRATA QA Contact: yafu <yafu>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 8.1CC: fjin, jdenemar, laine, lmen, xuzhang, yafu
Target Milestone: rcKeywords: Automation, Regression
Target Release: 8.1   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: libvirt-5.6.0-2.el8 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2019-11-06 07:18:55 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description yalzhang@redhat.com 2019-08-15 05:39:10 UTC
Description of problem:
Destroy network use polkit access control failed as access denied

Version-Release number of selected component (if applicable):
# rpm -q libvirt-libs polkit
libvirt-libs-5.6.0-1.module+el8.1.0+3890+4d3d259c.x86_64
polkit-0.115-8.el8.x86_64

How reproducible:
100%

Steps to Reproduce:
1. Setup:
1). Ensure polkit is installed:
# rpm -qa|grep polkit 
polkit-libs-0.115-8.el8.x86_64
polkit-0.115-8.el8.x86_64
polkit-pkla-compat-0.1-12.el8.x86_64
2).Add a normal user 
#useradd test1 
#passwd test1
3).Enable 'polkit' as the Access control driver 
#vim /etc/libvirt/libvirtd.conf
access_drivers = [ "polkit" ] 
4).Granted local user permission to connect to libvirt in full read-write mode
#vi /etc/libvirt/libvirtd.conf 
unix_sock_rw_perms = "0777"
auth_unix_rw = "none"
5).Restart libvirtd:
# systemctl restart libvirtd

2. Prepare an active network
# virsh net-list
 Name        State    Autostart   Persistent
----------------------------------------------
 definebr1   active   no          no

3. Prepare the polkit rule as below:
# cat /etc/polkit-1/rules.d/100-libvirt-acl.rules
polkit.addRule(function(action, subject) {
    if (action.id == 'org.libvirt.api.network.stop' && subject.user == 'test1') {
        if (action.lookup('connect_driver') == 'QEMU' && action.lookup('network_name') == 'definebr1') {
            return polkit.Result.YES;
        } else {
            return polkit.Result.NO;
        }
    }
});

4. login as unprivileged user test1:
# su - test1
$ whoami
test1 
$ virsh -c qemu:///system
Welcome to virsh, the virtualization interactive terminal.

Type:  'help' for help with commands
       'quit' to quit

virsh # net-list 
 Name        State    Autostart   Persistent
----------------------------------------------
 default     active   yes         yes
 definebr1   active   no          no

virsh # net-destroy definebr1
error: Failed to destroy network definebr1
error: access denied: 'QEMU' denied access

virsh # 


Actual results:
Destroy network use polkit access control failed as access denied

Expected results:
The network should be destroyed successfully with the correct polkit rule

Additional info:
It works with the polkit rule as follows:
polkit.addRule(function(action, subject) {
    if (action.id == 'org.libvirt.api.network.search-ports' && subject.user == 'test1') {
        if (action.lookup('connect_driver') == 'network' && action.lookup('network_name') == 'definebr1') {
            return polkit.Result.YES;
        } else {
            return polkit.Result.NO;
        }
    }
});

# su - test1 -c '/usr/bin/virsh -c network:///system net-destroy definebr1'
Network definebr1 destroyed

Comment 1 yafu 2019-08-15 06:06:22 UTC
The issue was caused by  commit e69444e1,  it is caused by the inconsistent order of enum "virAccessPermNetwork".
#cat src/access/viraccessperm.c
57 VIR_ENUM_IMPL(virAccessPermNetwork,
 58               VIR_ACCESS_PERM_NETWORK_LAST,
 59               "getattr", "read", "write",
 60               "save", "delete", "start", "stop",
 61               "search_ports",
 62 );
#cat src/access/viraccessperm.h
407     /**
408      * @desc: Start network
409      * @message: Starting network requires authorization
410      */
411     VIR_ACCESS_PERM_NETWORK_START,
412
413     /**
414      * @desc: List network ports
415      * @message: Listing network ports requires authorization
416      */
417     VIR_ACCESS_PERM_NETWORK_SEARCH_PORTS,
418
419     /**
420      * @desc: Stop network
421      * @message: Stopping network requires authorization
422      */
423     VIR_ACCESS_PERM_NETWORK_STOP,
424
425     VIR_ACCESS_PERM_NETWORK_LAST
426 } virAccessPermNetwork;

Comment 2 Laine Stump 2019-08-15 20:44:01 UTC
Thanks for locating the cause! I posted a fix upstream:

https://www.redhat.com/archives/libvir-list/2019-August/msg00586.html

Comment 3 Laine Stump 2019-08-17 00:56:10 UTC
FIx pushed upstream:

commit 8d6eaf5e099dab8400aa76bcc9a0ac74ff6f46e1
Author: Laine Stump <laine>
Date:   Thu Aug 15 16:34:21 2019 -0400

    access: fix incorrect addition to virAccessPermNetwork

Comment 6 yafu 2019-08-22 07:29:58 UTC
Reproduced with libvirt-5.6.0-1.x86_64.

Verified with libvirt-5.6.0-2.el8.x86_64.
Test steps:
1. Setup:
1). Ensure polkit is installed:
# rpm -qa|grep polkit 
polkit-libs-0.115-8.el8.x86_64
polkit-0.115-8.el8.x86_64
polkit-pkla-compat-0.1-12.el8.x86_64
2).Add a normal user 
#useradd test1 
#passwd test1
3).Enable 'polkit' as the Access control driver 
#vim /etc/libvirt/libvirtd.conf
access_drivers = [ "polkit" ] 
4).Granted local user permission to connect to libvirt in full read-write mode
#vi /etc/libvirt/libvirtd.conf 
unix_sock_rw_perms = "0777"
auth_unix_rw = "none"
5).Restart libvirtd:
# systemctl restart libvirtd

2. Prepare an active network
# virsh net-list
 Name        State    Autostart   Persistent
----------------------------------------------
 definebr1   active   no          no

3. Prepare the polkit rule as below:
# cat /etc/polkit-1/rules.d/100-libvirt-acl.rules
polkit.addRule(function(action, subject) {
    if (action.id == 'org.libvirt.api.network.stop' && subject.user == 'test1') {
        if (action.lookup('connect_driver') == 'QEMU' && action.lookup('network_name') == 'definebr1') {
            return polkit.Result.YES;
        } else {
            return polkit.Result.NO;
        }
    }
});

4.#su - test1 -c '/usr/bin/virsh -c network:///system net-destroy definebr1'
Network definebr1 destroyed

Comment 8 errata-xmlrpc 2019-11-06 07:18:55 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2019:3723