[libvirt] [PATCH v2] examples: Add example polkit ACL rules

Daniel P. Berrange berrange at redhat.com
Fri Sep 4 12:26:17 UTC 2015


On Fri, Sep 04, 2015 at 02:19:09PM +0200, Jiri Denemark wrote:
> Creating ACL rules is not exactly easy and existing examples are pretty
> simple. This patch adds a somewhat complex example which defines several
> roles. Admins can do everything, operators can do basic operations
> on any domain and several groups of users who act as operators but only
> on a limited set of domains.
> 
> Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
> ---
>  Makefile.am                       |   2 +-
>  configure.ac                      |   1 +
>  examples/polkit/Makefile.am       |  17 ++++++
>  examples/polkit/libvirt-acl.rules | 115 ++++++++++++++++++++++++++++++++++++++
>  libvirt.spec.in                   |   3 +
>  5 files changed, 137 insertions(+), 1 deletion(-)
>  create mode 100644 examples/polkit/Makefile.am
>  create mode 100644 examples/polkit/libvirt-acl.rules
> 
> diff --git a/Makefile.am b/Makefile.am
> index 91b943b..d338d5a 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -23,7 +23,7 @@ SUBDIRS = . gnulib/lib include src daemon tools docs gnulib/tests \
>    tests po examples/object-events examples/hellolibvirt \
>    examples/dominfo examples/domsuspend examples/apparmor \
>    examples/xml/nwfilter examples/openauth examples/systemtap \
> -  tools/wireshark examples/dommigrate \
> +  tools/wireshark examples/dommigrate examples/polkit \
>    examples/lxcconvert examples/domtop
>  
>  ACLOCAL_AMFLAGS = -I m4
> diff --git a/configure.ac b/configure.ac
> index 8471a46..136c2e7 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -2809,6 +2809,7 @@ AC_CONFIG_FILES([\
>          examples/systemtap/Makefile \
>          examples/xml/nwfilter/Makefile \
>          examples/lxcconvert/Makefile \
> +        examples/polkit/Makefile \
>          tools/wireshark/Makefile \
>          tools/wireshark/src/Makefile])
>  AC_OUTPUT
> diff --git a/examples/polkit/Makefile.am b/examples/polkit/Makefile.am
> new file mode 100644
> index 0000000..4d213e8
> --- /dev/null
> +++ b/examples/polkit/Makefile.am
> @@ -0,0 +1,17 @@
> +## Copyright (C) 2015 Red Hat, Inc.
> +##
> +## This library is free software; you can redistribute it and/or
> +## modify it under the terms of the GNU Lesser General Public
> +## License as published by the Free Software Foundation; either
> +## version 2.1 of the License, or (at your option) any later version.
> +##
> +## This library is distributed in the hope that it will be useful,
> +## but WITHOUT ANY WARRANTY; without even the implied warranty of
> +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +## Lesser General Public License for more details.
> +##
> +## You should have received a copy of the GNU Lesser General Public
> +## License along with this library.  If not, see
> +## <http://www.gnu.org/licenses/>.
> +
> +EXTRA_DIST = libvirt-acl.rules
> diff --git a/examples/polkit/libvirt-acl.rules b/examples/polkit/libvirt-acl.rules
> new file mode 100644
> index 0000000..5c26593
> --- /dev/null
> +++ b/examples/polkit/libvirt-acl.rules
> @@ -0,0 +1,115 @@


It would be beneficial to put some docs in this file header here
to explain to people what this example is achieving.

> +function Role(name) {
> +    this.name = name;
> +
> +    this.users = [];
> +    this.groups = [];
> +
> +    this.check = function(subject, api, domain) {
> +        var validUser = false
> +
> +        if (this.users.indexOf(subject.user) >= 0) {
> +            validUser = true;
> +        } else {
> +            for (var i = 0; i < subject.groups.length; i++) {
> +                if (this.groups.indexOf(subject.groups[i]) >= 0) {
> +                    validUser = true;
> +                    break;
> +                }
> +            }
> +        }
> +
> +        if (validUser &&
> +            (this.name == "admin" ||
> +             !domain ||
> +             (this.domains && domain.match(this.domains)))) {
> +            var msg = "Access granted: " +
> +                      "user = " + subject.user +
> +                      ", groups = [" + subject.groups + "]" +
> +                      ", role = " + this.name +
> +                      ", api = " + api;
> +            if (domain)
> +                msg += ", domain = " + domain;
> +            polkit.log(msg);
> +            return true
> +        }
> +
> +        return false;
> +    };
> +}
> +
> +
> +/* Basic operations and monitoring on a limited set of domains. */
> +var userA = new Role("userA");
> +userA.domains = /^a/;
> +userA.users = ["userA1", "userA2", "userA3", "multiUser"];
> +userA.groups = ["groupA1", "groupA2"];
> +
> +var userB = new Role("userB");
> +userB.domains = /^b/;
> +userB.users = ["userB1", "userB2", "userB3", "multiUser"];
> +userB.groups = ["groupB1", "groupB2", "multiGroup"];
> +
> +var userC = new Role("userC");
> +userC.domains = /^c/;
> +userC.users = ["userC1", "userC2", "userC3"];
> +userC.groups = ["groupC1", "groupC2", "multiGroup"];
> +
> +/* Same as users but on any domain. */
> +var operator = new Role("operator");
> +operator.domains = /.*/;
> +operator.users = ["powerUser1", "powerUser2"];
> +operator.groups = ["powerGroup1", "powerGroup2", "powerGroup3"];
> +
> +var users = [operator, userA, userB, userC];
> +
> +/* Full access. */
> +var admin = new Role("admin");
> +admin.users = ["adminUser1"];
> +admin.groups = ["adminGroup1"];
> +
> +
> +restrictedActions = [
> +    "domain.core-dump",
> +    "domain.fs-freeze",
> +    "domain.fs-trim",
> +    "domain.getattr",
> +    "domain.hibernate",
> +    "domain.init-control",
> +    "domain.inject-nmi",
> +    "domain.open-device",
> +    "domain.open-graphics",
> +    "domain.pm-control",
> +    "domain.read",
> +    "domain.reset",
> +    "domain.save",
> +    "domain.screenshot",
> +    "domain.send-input",
> +    "domain.send-signal",
> +    "domain.set-password",
> +    "domain.set-time",
> +    "domain.snapshot",
> +    "domain.start",
> +    "domain.stop",
> +    "domain.suspend"
> +];
> +
> +polkit.addRule(function(action, subject) {
> +    if (action.id.indexOf("org.libvirt.api.") != 0)
> +        return polkit.Result.NOT_HANDLED;
> +
> +    var api = action.id.replace("org.libvirt.api.", "");
> +    var domain = action.lookup("domain_name");
> +
> +    if (admin.check(subject, api, domain))
> +        return polkit.Result.YES;
> +
> +    if (restrictedActions.indexOf(api) < 0)
> +        return polkit.Result.NOT_HANDLED;
> +
> +    for (var i = 0; i < users.length; i++) {
> +        if (users[i].check(subject, api, domain))
> +            return polkit.Result.YES;
> +    }
> +
> +    return polkit.Result.NO;
> +});
> diff --git a/libvirt.spec.in b/libvirt.spec.in
> index 78a4cc3..6f6b191 100644
> --- a/libvirt.spec.in
> +++ b/libvirt.spec.in
> @@ -2039,6 +2039,9 @@ exit 0
>      %endif # ! %{with_driver_modules}
>  
>      %if %{with_network}
> +
> +%doc examples/polkit/*.rules
> +
>  %files daemon-config-network
>  %defattr(-, root, root)
>  %dir %{_datadir}/libvirt/networks/
> -- 

ACK

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|




More information about the libvir-list mailing list