Authentication & access control

When connecting to libvirt, some connections may require client authentication before allowing use of the APIs. The set of possible authentication mechanisms is administrator controlled, independent of applications using libvirt.

Client configuration

When connecting to a remote hypervisor which requires authentication, most libvirt applications will prompt the user for the credentials. It is also possible to provide a client configuration file containing all the authentication credentials, avoiding any interaction. Libvirt will look for the authentication file using the following sequence:

  1. The file path specified by the $LIBVIRT_AUTH_FILE environment variable.
  2. The file path specified by the "authfile=/some/file" URI query parameter
  3. The file $XDG_CONFIG_DIR/libvirt/auth.conf
  4. The file /etc/libvirt/auth.conf

The auth configuration file uses the traditional ".ini" style syntax. There are two types of groups that can be present in the config. First there are one or more credential sets, which provide the actual authentication credentials. The keys within the group may be:

Each set of credentials has a name, which is part of the group entry name. Overall the syntax is

[credentials-$NAME]
credname1=value1
credname2=value2

For example, to define two sets of credentials used for production and test machines, using libvirtd, and a further ESX server for dev:

[credentials-test]
authname=fred
password=123456

[credentials-prod]
authname=bar
password=letmein

[credentials-dev]
username=joe
password=hello

The second set of groups provide mappings of credentials to specific machine services. The config file group names compromise the service type and host:

[auth-$SERVICE-$HOSTNAME]
credentials=$CREDENTIALS

For example, following the previous example, here is how to list some machines

[auth-libvirt-test1.example.com]
credentials=test

[auth-libvirt-test2.example.com]
credentials=test

[auth-libvirt-demo3.example.com]
credentials=test

[auth-libvirt-prod1.example.com]
credentials=prod

[auth-esx-dev1.example.com]
credentials=dev

The following service types are known to libvirt

  1. libvirt - used for connections to a libvirtd server, which is configured with SASL auth
  2. ssh - used for connections to a Phyp server over SSH
  3. esx - used for connections to an ESX or VirtualCenter server
  4. xen - used for connections to a Xen Enterprise sever using XenAPI

Applications using libvirt are free to use this same configuration file for storing other credentials. For example, it can be used to storage VNC or SPICE login credentials

Server configuration

The libvirt daemon allows the administrator to choose the authentication mechanisms used for client connections on each network socket independently. This is primarily controlled via the libvirt daemon master config file in /etc/libvirt/libvirtd.conf. Each of the libvirt sockets can have its authentication mechanism configured independently. There is currently a choice of none, polkit, and sasl. The SASL scheme can be further configured to choose between a large number of different mechanisms.

UNIX socket permissions/group

If libvirt does not contain support for PolicyKit, then access control for the UNIX domain socket is done using traditional file user/group ownership and permissions. There are 2 sockets, one for full read-write access, the other for read-only access. The RW socket will be restricted (mode 0700) to only allow the root user to connect. The read-only socket will be open access (mode 0777) to allow any user to connect.

To allow non-root users greater access, the libvirtd.conf file can be edited to change the permissions via the unix_sock_rw_perms, config parameter and to set a user group via the unix_sock_group parameter. For example, setting the former to mode 0770 and the latter wheel would let any user in the wheel group connect to the libvirt daemon.

UNIX socket PolicyKit auth

If libvirt contains support for PolicyKit, then access control options are more advanced. The unix_sock_auth parameter will default to polkit, and the file permissions will default to 0777 even on the RW socket. Upon connecting to the socket, the client application will be required to identify itself with PolicyKit. The default policy for the RW daemon socket will require any application running in the current desktop session to authenticate using the user's password. This is akin to sudo auth, but does not require that the client application ultimately run as root. Default policy will still allow any application to connect to the RO socket.

The default policy can be overridden by creating a new policy file in the local override directory /etc/polkit-1/localauthority/50-local.d/. Policy files should have a unique name ending with .pkla. Using reverse DNS naming works well. Information on the options available can be found by reading the pklocalauthority man page. The two libvirt daemon actions available are named org.libvirt.unix.manage for full management access, and org.libvirt.unix.monitor for read-only access.

As an example, this gives the user fred full management access:

[Allow fred libvirt management permissions]
Identity=unix-user:fred
Action=org.libvirt.unix.manage
ResultAny=yes
ResultInactive=yes
ResultActive=yes

Further examples of PolicyKit setup can be found on the wiki page.

Username/password auth

The plain TCP socket of the libvirt daemon defaults to using SASL for authentication. The SASL mechanism configured by default is DIGEST-MD5, which provides a basic username+password style authentication. It also provides for encryption of the data stream, so the security of the plain TCP socket is on a par with that of the TLS socket. If desired the UNIX socket and TLS socket can also have SASL enabled by setting the auth_unix_ro, auth_unix_rw, auth_tls config params in libvirt.conf.

Out of the box, no user accounts are defined, so no clients will be able to authenticate on the TCP socket. Adding users and setting their passwords is done with the saslpasswd2 command. When running this command it is important to tell it that the appname is libvirt. As an example, to add a user fred, run

# saslpasswd2 -a libvirt fred
Password: xxxxxx
Again (for verification): xxxxxx

To see a list of all accounts the sasldblistusers2 command can be used. This command expects to be given the path to the libvirt user database, which is kept in /etc/libvirt/passwd.db

# sasldblistusers2 -f /etc/libvirt/passwd.db
fred@t60wlan.home.berrange.com: userPassword

Finally, to disable a user's access, the saslpasswd2 command can be used again:

# saslpasswd2 -a libvirt -d fred

Kerberos auth

The plain TCP socket of the libvirt daemon defaults to using SASL for authentication. The SASL mechanism configured by default is DIGEST-MD5, which provides a basic username+password style authentication. To enable Kerberos single-sign-on instead, the libvirt SASL configuration file must be changed. This is /etc/sasl2/libvirt.conf. The mech_list parameter must first be changed to gssapi instead of the default digest-md5. If SASL is enabled on the UNIX and/or TLS sockets, Kerberos will also be used for them. Like DIGEST-MD5, the Kerberos mechanism provides data encryption of the session.

Some operating systems do not install the SASL kerberos plugin by default. It may be necessary to install a sub-package such as cyrus-sasl-gssapi. To check whether the Kerberos plugin is installed run the pluginviewer program and verify that gssapi is listed,eg:

# pluginviewer
...snip...
Plugin "gssapiv2" [loaded],     API version: 4
        SASL mechanism: GSSAPI, best SSF: 56
        security flags: NO_ANONYMOUS|NO_PLAINTEXT|NO_ACTIVE|PASS_CREDENTIALS|MUTUAL_AUTH
        features: WANT_CLIENT_FIRST|PROXY_AUTHENTICATION|NEED_SERVER_FQDN

Next it is necessary for the administrator of the Kerberos realm to issue a principle for the libvirt server. There needs to be one principle per host running the libvirt daemon. The principle should be named libvirt/full.hostname@KERBEROS.REALM. This is typically done by running the kadmin.local command on the Kerberos server, though some Kerberos servers have alternate ways of setting up service principles. Once created, the principle should be exported to a keytab, copied to the host running the libvirt daemon and placed in /etc/libvirt/krb5.tab

# kadmin.local
kadmin.local: add_principal libvirt/foo.example.com
Enter password for principal "libvirt/foo.example.com@EXAMPLE.COM":
Re-enter password for principal "libvirt/foo.example.com@EXAMPLE.COM":
Principal "libvirt/foo.example.com@EXAMPLE.COM" created.

kadmin.local:  ktadd -k /root/libvirt-foo-example.tab libvirt/foo.example.com@EXAMPLE.COM
Entry for principal libvirt/foo.example.com@EXAMPLE.COM with kvno 4, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/root/libvirt-foo-example.tab.
Entry for principal libvirt/foo.example.com@EXAMPLE.COM with kvno 4, encryption type ArcFour with HMAC/md5 added to keytab WRFILE:/root/libvirt-foo-example.tab.
Entry for principal libvirt/foo.example.com@EXAMPLE.COM with kvno 4, encryption type DES with HMAC/sha1 added to keytab WRFILE:/root/libvirt-foo-example.tab.
Entry for principal libvirt/foo.example.com@EXAMPLE.COM with kvno 4, encryption type DES cbc mode with RSA-MD5 added to keytab WRFILE:/root/libvirt-foo-example.tab.

kadmin.local: quit

# scp /root/libvirt-foo-example.tab root@foo.example.com:/etc/libvirt/krb5.tab
# rm /root/libvirt-foo-example.tab

Any client application wishing to connect to a Kerberos enabled libvirt server merely needs to run kinit to gain a user principle. This may well be done automatically when a user logs into a desktop session, if PAM is setup to authenticate against Kerberos.