Product SiteDocumentation Site

Глава 55. Управление доступом в виртуальной инфраструктуре

Права пользователя могут управляться с помощью правил polkit.
В каталоге /usr/share/polkit-1/actions/ имеются два файла с описанием возможных действий для работы с ВМ, предоставленные разработчиками libvirt:
  • файл org.libvirt.unix.policy описывает мониторинг ВМ и управление ими;
  • в файле org.libvirt.api.policy перечислены конкретные действия (остановка, перезапуск и т. д.), которые возможны, если предыдущая проверка пройдена.
Перечисление конкретных свойств с комментариями доступно в файле /usr/share/polkit-1/actions/org.libvirt.api.policy.
В libvirt названия объектов и разрешений отображаются в имена polkit действий, по схеме:
org.libvirt.api.$объект.$разрешение
Например, разрешение search-storage-vols на объекте storage_pool отображено к действию polkit:
org.libvirt.api.storage-pool.search-storage-vols
Чтобы определить правила авторизации, polkit должен однозначно определить объект. Libvirt предоставляет ряд атрибутов для определения объектов при выполнении проверки прав доступа. Набор атрибутов изменяется в зависимости от типа объекта.
Пример тонкой настройки. Есть две виртуальные машины: alt1, alt2. Необходимо разрешить пользователю test (должен быть в группе vmusers) действия только с доменом alt1. Для этого необходимо выполнить следующие действия:
  1. Раскомментировать в файле /etc/libvirt/libvirtd.conf строку:
    access_drivers = [ "polkit" ]
    
  2. Перезапустить libvirt:
    systemctl restart libvirtd
    
  3. Создать файл /etc/polkit-1/rules.d/100-libvirt-acl.rules (имя произвольно) следующего вида:
    ==========================
    polkit.addRule(function(action, subject) {
    // разрешить пользователю test действия с доменом "alt1"
    if (action.id.indexOf("org.libvirt.api.domain.") ==0  &&
       subject.user == "test")
        {
            if (action.lookup("domain_name") == 'alt1')
            {
                return polkit.Result.YES;
            }
            else
            {
                return polkit.Result.NO;
            }
        }
    else {
    // разрешить пользователю test действия с
    //подключениями, хранилищем и прочим
            if (action.id.indexOf("org.libvirt.api.") == 0 &&
            subject.user == "test")
            {
                polkit.log("org.libvirt.api.Yes");
                return polkit.Result.YES;
            }
            else
            {
                return polkit.Result.NO;
            }
        }
    })
    ================================
    
  4. Перелогиниться.
В результате выполненных действий пользователю test машина alt1 видна, а машина alt2 — нет.
 Права можно настраивать более тонко, например, разрешив пользователю test запускать ВМ, но запретить ему все остальные действия с ней, для этого надо разрешить действие org.libvirt.api.domain.start:
==========================
polkit.addRule(function(action, subject)
{
    // разрешить пользователю test только запускать ВМ в
    // домене "alt1"
    if (action.id. == "org.libvirt.api.domain.start") &&
    subject.user == "test")
    {
        if (action.lookup("domain_name") == 'alt1')
        {
           return polkit.Result.YES;
        }
        else
        {
            return polkit.Result.NO;
        }
    }
});
==========================
Предоставить право запускать ВМ, только пользователям группы wheel:
if (action.id == "org.libvirt.api.domain.start")
{
    if (subject.isInGroup("wheel"))
    {
        return polkit.Result.YES;
    }
    else
    {
        return polkit.Result.NO;
    }
};
Предоставить право останавливать ВМ, только пользователям группы wheel:
if (action.id == "org.libvirt.api.domain.stop")
{
    if (subject.isInGroup("wheel"))
    {
        return polkit.Result.YES;
    }
    else
    {
        return polkit.Result.NO;
    }
};
Можно также вести файл журнала, используя правила polkit. Например, делать запись в журнал при старте ВМ:
if (action.id.match("org.libvirt.api.domain.start"))
{
    polkit.log("action=" + action);
    polkit.log("subject=" + subject);
    return polkit.Result.YES;
}
Запись в журнал при останове ВМ:
if (action.id.match("org.libvirt.api.domain.stop"))
{
    polkit.log("action=" + action);
    polkit.log("subject=" + subject);
    return polkit.Result.YES;
}