mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-03 11:35:19 +00:00
docs: html.in: Convert aclpolkit to rst
Signed-off-by: Erik Skultety <eskultet@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com>
This commit is contained in:
parent
10bf55c99f
commit
d91482807e
@ -1,523 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<body>
|
|
||||||
<h1>Polkit access control</h1>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Libvirt's client <a href="acl.html">access control framework</a> allows
|
|
||||||
administrators to setup fine grained permission rules across client users,
|
|
||||||
managed objects and API operations. This allows client connections
|
|
||||||
to be locked down to a minimal set of privileges. The polkit driver
|
|
||||||
provides a simple implementation of the access control framework.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<ul id="toc"></ul>
|
|
||||||
|
|
||||||
<h2><a id="intro">Introduction</a></h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
A default install of libvirt will typically use
|
|
||||||
<a href="https://www.freedesktop.org/wiki/Software/polkit/">polkit</a>
|
|
||||||
to authenticate the initial user connection to libvirtd. This is a
|
|
||||||
very coarse grained check though, either allowing full read-write
|
|
||||||
access to all APIs, or just read-only access. The polkit access
|
|
||||||
control driver in libvirt builds on this capability to allow for
|
|
||||||
fine grained control over the operations a user may perform on an
|
|
||||||
object.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2><a id="perms">Permission names</a></h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The libvirt <a href="acl.html#perms">object names and permission names</a>
|
|
||||||
are mapped onto polkit action names using the simple pattern:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<pre>org.libvirt.api.$object.$permission
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The only caveat is that any underscore characters in the
|
|
||||||
object or permission names are converted to hyphens. So,
|
|
||||||
for example, the <code>search_storage_vols</code> permission
|
|
||||||
on the <code>storage_pool</code> object maps to the polkit
|
|
||||||
action:
|
|
||||||
</p>
|
|
||||||
<pre>org.libvirt.api.storage-pool.search-storage-vols
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The default policy for any permission which corresponds to
|
|
||||||
a "read only" operation, is to allow access. All other
|
|
||||||
permissions default to deny access.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2><a id="attrs">Object identity attributes</a></h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
To allow polkit authorization rules to be written to match
|
|
||||||
against individual object instances, libvirt provides a number
|
|
||||||
of authorization detail attributes when performing a permission
|
|
||||||
check. The set of attributes varies according to the type
|
|
||||||
of object being checked
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3><a id="object_connect">virConnectPtr</a></h3>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Attribute</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>connect_driver</td>
|
|
||||||
<td>Name of the libvirt connection driver</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3><a id="object_domain">virDomainPtr</a></h3>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Attribute</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>connect_driver</td>
|
|
||||||
<td>Name of the libvirt connection driver</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>domain_name</td>
|
|
||||||
<td>Name of the domain, unique to the local host</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>domain_uuid</td>
|
|
||||||
<td>UUID of the domain, globally unique</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3><a id="object_interface">virInterfacePtr</a></h3>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Attribute</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>connect_driver</td>
|
|
||||||
<td>Name of the libvirt connection driver</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>interface_name</td>
|
|
||||||
<td>Name of the network interface, unique to the local host</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>interface_macaddr</td>
|
|
||||||
<td>MAC address of the network interface, not unique</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3><a id="object_network">virNetworkPtr</a></h3>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Attribute</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>connect_driver</td>
|
|
||||||
<td>Name of the libvirt connection driver</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>network_name</td>
|
|
||||||
<td>Name of the network, unique to the local host</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>network_uuid</td>
|
|
||||||
<td>UUID of the network, globally unique</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3><a id="object_node_device">virNodeDevicePtr</a></h3>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Attribute</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>connect_driver</td>
|
|
||||||
<td>Name of the libvirt connection driver</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>node_device_name</td>
|
|
||||||
<td>Name of the node device, unique to the local host</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3><a id="object_nwfilter">virNWFilterPtr</a></h3>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Attribute</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>connect_driver</td>
|
|
||||||
<td>Name of the libvirt connection driver</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>nwfilter_name</td>
|
|
||||||
<td>Name of the network filter, unique to the local host</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>nwfilter_uuid</td>
|
|
||||||
<td>UUID of the network filter, globally unique</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3><a id="object_secret">virSecretPtr</a></h3>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Attribute</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>connect_driver</td>
|
|
||||||
<td>Name of the libvirt connection driver</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>secret_uuid</td>
|
|
||||||
<td>UUID of the secret, globally unique</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>secret_usage_volume</td>
|
|
||||||
<td>Name of the associated volume, if any</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>secret_usage_ceph</td>
|
|
||||||
<td>Name of the associated Ceph server, if any</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>secret_usage_target</td>
|
|
||||||
<td>Name of the associated iSCSI target, if any</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>secret_usage_name</td>
|
|
||||||
<td>Name of the associated TLS secret, if any</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3><a id="object_storage_pool">virStoragePoolPtr</a></h3>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Attribute</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>connect_driver</td>
|
|
||||||
<td>Name of the libvirt connection driver</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>pool_name</td>
|
|
||||||
<td>Name of the storage pool, unique to the local host</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>pool_uuid</td>
|
|
||||||
<td>UUID of the storage pool, globally unique</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3><a id="object_storage_vol">virStorageVolPtr</a></h3>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Attribute</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>connect_driver</td>
|
|
||||||
<td>Name of the libvirt connection driver</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>pool_name</td>
|
|
||||||
<td>Name of the storage pool, unique to the local host</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>pool_uuid</td>
|
|
||||||
<td>UUID of the storage pool, globally unique</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>vol_name</td>
|
|
||||||
<td>Name of the storage volume, unique to the pool</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>vol_key</td>
|
|
||||||
<td>Key of the storage volume, globally unique</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h2><a id="connect_driver">Hypervisor Driver connect_driver</a></h2>
|
|
||||||
<p>
|
|
||||||
The <code>connect_driver</code> parameter describes the
|
|
||||||
client's <a href="remote.html">remote Connection Driver</a>
|
|
||||||
name based on the <a href="uri.html">URI</a> used for the
|
|
||||||
connection.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="since">Since 4.1.0</span>, when calling an API
|
|
||||||
outside the scope of the primary connection driver, the
|
|
||||||
primary driver will attempt to open a secondary connection
|
|
||||||
to the specific API driver in order to process the API. For
|
|
||||||
example, when hypervisor domain processing needs to make an
|
|
||||||
API call within the storage driver or the network filter driver
|
|
||||||
an attempt to open a connection to the "storage" or "nwfilter"
|
|
||||||
driver will be made. Similarly, a "storage" primary connection
|
|
||||||
may need to create a connection to the "secret" driver in order
|
|
||||||
to process secrets for the API. If successful, then calls to
|
|
||||||
those API's will occur in the <code>connect_driver</code> context
|
|
||||||
of the secondary connection driver rather than in the context of
|
|
||||||
the primary driver. This affects the <code>connect_driver</code>
|
|
||||||
returned from rule generation from the <code>action.loookup</code>
|
|
||||||
function. The following table provides a list of the various
|
|
||||||
connection drivers and the <code>connect_driver</code> name
|
|
||||||
used by each regardless of primary or secondary connection.
|
|
||||||
The access denied error message from libvirt will list the
|
|
||||||
connection driver by name that denied the access.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3><a id="object_connect_driver">Connection Driver Name</a></h3>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Connection Driver</th>
|
|
||||||
<th><code>connect_driver</code> name</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>bhyve</td>
|
|
||||||
<td>bhyve</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>esx</td>
|
|
||||||
<td>ESX</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>hyperv</td>
|
|
||||||
<td>Hyper-V</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>interface</td>
|
|
||||||
<td>interface</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>xen</td>
|
|
||||||
<td>Xen</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>lxc</td>
|
|
||||||
<td>LXC</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>network</td>
|
|
||||||
<td>network</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>nodedev</td>
|
|
||||||
<td>nodedev</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>nwfilter</td>
|
|
||||||
<td>NWFilter</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>openvz</td>
|
|
||||||
<td>OPENVZ</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>qemu</td>
|
|
||||||
<td>QEMU</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>secret</td>
|
|
||||||
<td>secret</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>storage</td>
|
|
||||||
<td>storage</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>vbox</td>
|
|
||||||
<td>VBOX</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>vmware</td>
|
|
||||||
<td>VMWARE</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>vz</td>
|
|
||||||
<td>vz</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
|
|
||||||
<h2><a id="user">User identity attributes</a></h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
At this point in time, the only attribute provided by
|
|
||||||
libvirt to identify the user invoking the operation
|
|
||||||
is the PID of the client program. This means that the
|
|
||||||
polkit access control driver is only useful if connections
|
|
||||||
to libvirt are restricted to its UNIX domain socket. If
|
|
||||||
connections are being made to a TCP socket, no identifying
|
|
||||||
information is available and access will be denied.
|
|
||||||
Also note that if the client is connecting via an SSH
|
|
||||||
tunnel, it is the local SSH user that will be identified.
|
|
||||||
In future versions, it is expected that more information
|
|
||||||
about the client user will be provided, including the
|
|
||||||
SASL / Kerberos username and/or x509 distinguished
|
|
||||||
name obtained from the authentication provider in use.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
<h2><a id="checks">Writing access control policies</a></h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
If using versions of polkit prior to 0.106 then it is only
|
|
||||||
possible to validate (user, permission) pairs via the <code>.pkla</code>
|
|
||||||
files. Fully validation of the (user, permission, object) triple
|
|
||||||
requires the new JavaScript <code>.rules</code> support that
|
|
||||||
was introduced in version 0.106. The latter is what will be
|
|
||||||
described here.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Libvirt does not ship any rules files by default. It merely
|
|
||||||
provides a definition of the default behaviour for each
|
|
||||||
action (permission). As noted earlier, permissions which
|
|
||||||
correspond to read-only operations in libvirt will be allowed
|
|
||||||
to all users by default; everything else is denied by default.
|
|
||||||
Defining custom rules requires creation of a file in the
|
|
||||||
<code>/etc/polkit-1/rules.d</code> directory with a name
|
|
||||||
chosen by the administrator (<code>100-libvirt-acl.rules</code>
|
|
||||||
would be a reasonable choice). See the <code>polkit(8)</code>
|
|
||||||
manual page for a description of how to write these files
|
|
||||||
in general. The key idea is to create a file containing
|
|
||||||
something like
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
polkit.addRule(function(action, subject) {
|
|
||||||
....logic to check 'action' and 'subject'...
|
|
||||||
});
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
In this code snippet above, the <code>action</code> object
|
|
||||||
instance will represent the libvirt permission being checked
|
|
||||||
along with identifying attributes for the object it is being
|
|
||||||
applied to. The <code>subject</code> meanwhile will identify
|
|
||||||
the libvirt client app (with the caveat above about it only
|
|
||||||
dealing with local clients connected via the UNIX socket).
|
|
||||||
On the <code>action</code> object, the permission name is
|
|
||||||
accessible via the <code>id</code> attribute, while the
|
|
||||||
object identifying attributes are exposed via the
|
|
||||||
<code>lookup</code> method.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
See
|
|
||||||
<a href="https://gitlab.com/libvirt/libvirt/-/tree/master/examples/polkit">source code</a>
|
|
||||||
for a more complex example.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3><a id="exconnect">Example: restricting ability to connect to drivers</a></h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Consider a local user <code>berrange</code>
|
|
||||||
who has been granted permission to connect to libvirt in
|
|
||||||
full read-write mode. The goal is to only allow them to
|
|
||||||
use the <code>QEMU</code> driver and not the Xen or LXC
|
|
||||||
drivers which are also available in libvirtd.
|
|
||||||
To achieve this we need to write a rule which checks
|
|
||||||
whether the <code>connect_driver</code> attribute
|
|
||||||
is <code>QEMU</code>, and match on an action
|
|
||||||
name of <code>org.libvirt.api.connect.getattr</code>. Using
|
|
||||||
the javascript rules format, this ends up written as
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
polkit.addRule(function(action, subject) {
|
|
||||||
if (action.id == "org.libvirt.api.connect.getattr" &&
|
|
||||||
subject.user == "berrange") {
|
|
||||||
if (action.lookup("connect_driver") == 'QEMU') {
|
|
||||||
return polkit.Result.YES;
|
|
||||||
} else {
|
|
||||||
return polkit.Result.NO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h3><a id="exdomain">Example: restricting access to a single domain</a></h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Consider a local user <code>berrange</code>
|
|
||||||
who has been granted permission to connect to libvirt in
|
|
||||||
full read-write mode. The goal is to only allow them to
|
|
||||||
see the domain called <code>demo</code> on the LXC driver.
|
|
||||||
To achieve this we need to write a rule which checks
|
|
||||||
whether the <code>connect_driver</code> attribute
|
|
||||||
is <code>LXC</code> and the <code>domain_name</code>
|
|
||||||
attribute is <code>demo</code>, and match on an action
|
|
||||||
name of <code>org.libvirt.api.domain.getattr</code>. Using
|
|
||||||
the javascript rules format, this ends up written as
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
polkit.addRule(function(action, subject) {
|
|
||||||
if (action.id == "org.libvirt.api.domain.getattr" &&
|
|
||||||
subject.user == "berrange") {
|
|
||||||
if (action.lookup("connect_driver") == 'LXC' &&
|
|
||||||
action.lookup("domain_name") == 'demo') {
|
|
||||||
return polkit.Result.YES;
|
|
||||||
} else {
|
|
||||||
return polkit.Result.NO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</pre>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
310
docs/aclpolkit.rst
Normal file
310
docs/aclpolkit.rst
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
.. role:: since
|
||||||
|
|
||||||
|
=====================
|
||||||
|
Polkit access control
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Libvirt's client `access control framework <acl.html>`__ allows
|
||||||
|
administrators to setup fine grained permission rules across client
|
||||||
|
users, managed objects and API operations. This allows client
|
||||||
|
connections to be locked down to a minimal set of privileges. The polkit
|
||||||
|
driver provides a simple implementation of the access control framework.
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
A default install of libvirt will typically use
|
||||||
|
`polkit <https://www.freedesktop.org/wiki/Software/polkit/>`__ to
|
||||||
|
authenticate the initial user connection to libvirtd. This is a very
|
||||||
|
coarse grained check though, either allowing full read-write access to
|
||||||
|
all APIs, or just read-only access. The polkit access control driver in
|
||||||
|
libvirt builds on this capability to allow for fine grained control over
|
||||||
|
the operations a user may perform on an object.
|
||||||
|
|
||||||
|
Permission names
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The libvirt `object names and permission names <acl.html#perms>`__ are
|
||||||
|
mapped onto polkit action names using the simple pattern:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
org.libvirt.api.$object.$permission
|
||||||
|
|
||||||
|
The only caveat is that any underscore characters in the object or
|
||||||
|
permission names are converted to hyphens. So, for example, the
|
||||||
|
``search_storage_vols`` permission on the ``storage_pool`` object maps
|
||||||
|
to the polkit action:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
org.libvirt.api.storage-pool.search-storage-vols
|
||||||
|
|
||||||
|
The default policy for any permission which corresponds to a "read only"
|
||||||
|
operation, is to allow access. All other permissions default to deny
|
||||||
|
access.
|
||||||
|
|
||||||
|
Object identity attributes
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
To allow polkit authorization rules to be written to match against
|
||||||
|
individual object instances, libvirt provides a number of authorization
|
||||||
|
detail attributes when performing a permission check. The set of
|
||||||
|
attributes varies according to the type of object being checked
|
||||||
|
|
||||||
|
virConnectPtr
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
============== =====================================
|
||||||
|
Attribute Description
|
||||||
|
============== =====================================
|
||||||
|
connect_driver Name of the libvirt connection driver
|
||||||
|
============== =====================================
|
||||||
|
|
||||||
|
virDomainPtr
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
============== ============================================
|
||||||
|
Attribute Description
|
||||||
|
============== ============================================
|
||||||
|
connect_driver Name of the libvirt connection driver
|
||||||
|
domain_name Name of the domain, unique to the local host
|
||||||
|
domain_uuid UUID of the domain, globally unique
|
||||||
|
============== ============================================
|
||||||
|
|
||||||
|
virInterfacePtr
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
+-------------------+---------------------------------------------------------+
|
||||||
|
| Attribute | Description |
|
||||||
|
+===================+=========================================================+
|
||||||
|
| connect_driver | Name of the libvirt connection driver |
|
||||||
|
+-------------------+---------------------------------------------------------+
|
||||||
|
| interface_name | Name of the network interface, unique to the local host |
|
||||||
|
+-------------------+---------------------------------------------------------+
|
||||||
|
| interface_macaddr | MAC address of the network interface, not unique |
|
||||||
|
+-------------------+---------------------------------------------------------+
|
||||||
|
|
||||||
|
virNetworkPtr
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
============== =============================================
|
||||||
|
Attribute Description
|
||||||
|
============== =============================================
|
||||||
|
connect_driver Name of the libvirt connection driver
|
||||||
|
network_name Name of the network, unique to the local host
|
||||||
|
network_uuid UUID of the network, globally unique
|
||||||
|
============== =============================================
|
||||||
|
|
||||||
|
virNodeDevicePtr
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
================ =================================================
|
||||||
|
Attribute Description
|
||||||
|
================ =================================================
|
||||||
|
connect_driver Name of the libvirt connection driver
|
||||||
|
node_device_name Name of the node device, unique to the local host
|
||||||
|
================ =================================================
|
||||||
|
|
||||||
|
virNWFilterPtr
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
============== ====================================================
|
||||||
|
Attribute Description
|
||||||
|
============== ====================================================
|
||||||
|
connect_driver Name of the libvirt connection driver
|
||||||
|
nwfilter_name Name of the network filter, unique to the local host
|
||||||
|
nwfilter_uuid UUID of the network filter, globally unique
|
||||||
|
============== ====================================================
|
||||||
|
|
||||||
|
virSecretPtr
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
=================== ===========================================
|
||||||
|
Attribute Description
|
||||||
|
=================== ===========================================
|
||||||
|
connect_driver Name of the libvirt connection driver
|
||||||
|
secret_uuid UUID of the secret, globally unique
|
||||||
|
secret_usage_volume Name of the associated volume, if any
|
||||||
|
secret_usage_ceph Name of the associated Ceph server, if any
|
||||||
|
secret_usage_target Name of the associated iSCSI target, if any
|
||||||
|
secret_usage_name Name of the associated TLS secret, if any
|
||||||
|
=================== ===========================================
|
||||||
|
|
||||||
|
virStoragePoolPtr
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
============== ==================================================
|
||||||
|
Attribute Description
|
||||||
|
============== ==================================================
|
||||||
|
connect_driver Name of the libvirt connection driver
|
||||||
|
pool_name Name of the storage pool, unique to the local host
|
||||||
|
pool_uuid UUID of the storage pool, globally unique
|
||||||
|
============== ==================================================
|
||||||
|
|
||||||
|
virStorageVolPtr
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
============== ==================================================
|
||||||
|
Attribute Description
|
||||||
|
============== ==================================================
|
||||||
|
connect_driver Name of the libvirt connection driver
|
||||||
|
pool_name Name of the storage pool, unique to the local host
|
||||||
|
pool_uuid UUID of the storage pool, globally unique
|
||||||
|
vol_name Name of the storage volume, unique to the pool
|
||||||
|
vol_key Key of the storage volume, globally unique
|
||||||
|
============== ==================================================
|
||||||
|
|
||||||
|
Hypervisor Driver connect_driver
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
The ``connect_driver`` parameter describes the client's `remote
|
||||||
|
Connection Driver <remote.html>`__ name based on the `URI <uri.html>`__
|
||||||
|
used for the connection.
|
||||||
|
|
||||||
|
:since:`Since 4.1.0`, when calling an API outside the scope of the primary
|
||||||
|
connection driver, the primary driver will attempt to open a secondary
|
||||||
|
connection to the specific API driver in order to process the API. For
|
||||||
|
example, when hypervisor domain processing needs to make an API call
|
||||||
|
within the storage driver or the network filter driver an attempt to
|
||||||
|
open a connection to the "storage" or "nwfilter" driver will be made.
|
||||||
|
Similarly, a "storage" primary connection may need to create a
|
||||||
|
connection to the "secret" driver in order to process secrets for the
|
||||||
|
API. If successful, then calls to those API's will occur in the
|
||||||
|
``connect_driver`` context of the secondary connection driver rather
|
||||||
|
than in the context of the primary driver. This affects the
|
||||||
|
``connect_driver`` returned from rule generation from the
|
||||||
|
``action.loookup`` function. The following table provides a list of the
|
||||||
|
various connection drivers and the ``connect_driver`` name used by each
|
||||||
|
regardless of primary or secondary connection. The access denied error
|
||||||
|
message from libvirt will list the connection driver by name that denied
|
||||||
|
the access.
|
||||||
|
|
||||||
|
Connection Driver Name
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
================= =======================
|
||||||
|
Connection Driver ``connect_driver`` name
|
||||||
|
================= =======================
|
||||||
|
bhyve bhyve
|
||||||
|
esx ESX
|
||||||
|
hyperv Hyper-V
|
||||||
|
interface interface
|
||||||
|
xen Xen
|
||||||
|
lxc LXC
|
||||||
|
network network
|
||||||
|
nodedev nodedev
|
||||||
|
nwfilter NWFilter
|
||||||
|
openvz OPENVZ
|
||||||
|
qemu QEMU
|
||||||
|
secret secret
|
||||||
|
storage storage
|
||||||
|
vbox VBOX
|
||||||
|
vmware VMWARE
|
||||||
|
vz vz
|
||||||
|
================= =======================
|
||||||
|
|
||||||
|
User identity attributes
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
At this point in time, the only attribute provided by libvirt to
|
||||||
|
identify the user invoking the operation is the PID of the client
|
||||||
|
program. This means that the polkit access control driver is only useful
|
||||||
|
if connections to libvirt are restricted to its UNIX domain socket. If
|
||||||
|
connections are being made to a TCP socket, no identifying information
|
||||||
|
is available and access will be denied. Also note that if the client is
|
||||||
|
connecting via an SSH tunnel, it is the local SSH user that will be
|
||||||
|
identified. In future versions, it is expected that more information
|
||||||
|
about the client user will be provided, including the SASL / Kerberos
|
||||||
|
username and/or x509 distinguished name obtained from the authentication
|
||||||
|
provider in use.
|
||||||
|
|
||||||
|
Writing access control policies
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
If using versions of polkit prior to 0.106 then it is only possible to
|
||||||
|
validate (user, permission) pairs via the ``.pkla`` files. Fully
|
||||||
|
validation of the (user, permission, object) triple requires the new
|
||||||
|
JavaScript ``.rules`` support that was introduced in version 0.106. The
|
||||||
|
latter is what will be described here.
|
||||||
|
|
||||||
|
Libvirt does not ship any rules files by default. It merely provides a
|
||||||
|
definition of the default behaviour for each action (permission). As
|
||||||
|
noted earlier, permissions which correspond to read-only operations in
|
||||||
|
libvirt will be allowed to all users by default; everything else is
|
||||||
|
denied by default. Defining custom rules requires creation of a file in
|
||||||
|
the ``/etc/polkit-1/rules.d`` directory with a name chosen by the
|
||||||
|
administrator (``100-libvirt-acl.rules`` would be a reasonable choice).
|
||||||
|
See the ``polkit(8)`` manual page for a description of how to write
|
||||||
|
these files in general. The key idea is to create a file containing
|
||||||
|
something like
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
polkit.addRule(function(action, subject) {
|
||||||
|
....logic to check 'action' and 'subject'...
|
||||||
|
});
|
||||||
|
|
||||||
|
In this code snippet above, the ``action`` object instance will
|
||||||
|
represent the libvirt permission being checked along with identifying
|
||||||
|
attributes for the object it is being applied to. The ``subject``
|
||||||
|
meanwhile will identify the libvirt client app (with the caveat above
|
||||||
|
about it only dealing with local clients connected via the UNIX socket).
|
||||||
|
On the ``action`` object, the permission name is accessible via the
|
||||||
|
``id`` attribute, while the object identifying attributes are exposed
|
||||||
|
via the ``lookup`` method.
|
||||||
|
|
||||||
|
See `source
|
||||||
|
code <https://gitlab.com/libvirt/libvirt/-/tree/master/examples/polkit>`__
|
||||||
|
for a more complex example.
|
||||||
|
|
||||||
|
Example: restricting ability to connect to drivers
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Consider a local user ``berrange`` who has been granted permission to
|
||||||
|
connect to libvirt in full read-write mode. The goal is to only allow
|
||||||
|
them to use the ``QEMU`` driver and not the Xen or LXC drivers which are
|
||||||
|
also available in libvirtd. To achieve this we need to write a rule
|
||||||
|
which checks whether the ``connect_driver`` attribute is ``QEMU``, and
|
||||||
|
match on an action name of ``org.libvirt.api.connect.getattr``. Using
|
||||||
|
the javascript rules format, this ends up written as
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
polkit.addRule(function(action, subject) {
|
||||||
|
if (action.id == "org.libvirt.api.connect.getattr" &&
|
||||||
|
subject.user == "berrange") {
|
||||||
|
if (action.lookup("connect_driver") == 'QEMU') {
|
||||||
|
return polkit.Result.YES;
|
||||||
|
} else {
|
||||||
|
return polkit.Result.NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Example: restricting access to a single domain
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Consider a local user ``berrange`` who has been granted permission to
|
||||||
|
connect to libvirt in full read-write mode. The goal is to only allow
|
||||||
|
them to see the domain called ``demo`` on the LXC driver. To achieve
|
||||||
|
this we need to write a rule which checks whether the ``connect_driver``
|
||||||
|
attribute is ``LXC`` and the ``domain_name`` attribute is ``demo``, and
|
||||||
|
match on an action name of ``org.libvirt.api.domain.getattr``. Using the
|
||||||
|
javascript rules format, this ends up written as
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
polkit.addRule(function(action, subject) {
|
||||||
|
if (action.id == "org.libvirt.api.domain.getattr" &&
|
||||||
|
subject.user == "berrange") {
|
||||||
|
if (action.lookup("connect_driver") == 'LXC' &&
|
||||||
|
action.lookup("domain_name") == 'demo') {
|
||||||
|
return polkit.Result.YES;
|
||||||
|
} else {
|
||||||
|
return polkit.Result.NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
@ -32,7 +32,6 @@ docs_assets = [
|
|||||||
|
|
||||||
docs_html_in_files = [
|
docs_html_in_files = [
|
||||||
'404',
|
'404',
|
||||||
'aclpolkit',
|
|
||||||
'api_extension',
|
'api_extension',
|
||||||
'api',
|
'api',
|
||||||
'apps',
|
'apps',
|
||||||
@ -106,6 +105,7 @@ docs_html_in_files = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
docs_rst_files = [
|
docs_rst_files = [
|
||||||
|
'aclpolkit',
|
||||||
'advanced-tests',
|
'advanced-tests',
|
||||||
'best-practices',
|
'best-practices',
|
||||||
'ci',
|
'ci',
|
||||||
|
Loading…
Reference in New Issue
Block a user