LINUX.ORG.RU
ФорумAdmin

Alt server 10.4 — не получается с sudoers.d

 , ,


0

1

Нужно разрешить некоему юзеру рестартовать некий сервис. Добавил юзера в группу wheel. Добавил строку в /etc/sudoers.d/user :

user ALL=(ALL:ALL) NOPASSWD: /sbin/systemctl restart userservice

В результате имеем:

[sudo] password for user:
Извините, пользователю user не разрешено выполнять «/sbin/systemctl restart userservice.service» как root на host-176.

В логе:

фев 01 00:02:14 host-176 sudo[277433]: UNSPECIFIED (__progname="sudo" uid=503 euid=0): pam_tcb(sudo:auth): conversation failed
фев 01 00:02:14 host-176 sudo[277433]: user : command not allowed ; HOST=host-176 ; TTY=pts/1 ; PWD=/home/user ; USER=root ; COMMAND=/sbin/systemctl restart userservice.service

Кто виноват и что делать?

Команду надо писать полностью.

user ALL=(ALL:ALL) NOPASSWD: /sbin/systemctl restart userservice.service

И я бы написал так:

user ALL=NOPASSWD: /sbin/systemctl restart userservice.service

Тебе же не надо, чтобы он выполнял эту команду от любого пользователя.

Aceler ★★★★★
()
Ответ на: комментарий от Aceler

Это выдача их по смыслу разрешаемого действия, а не по текстовому представлению команды для его выполнения. Примерно так работают chmod и выдача групп - они не зависят от того, как называется файл или группа. Ну то есть на момент выдачи прав эти имена указать надо, чтобы сослаться на объект, но если потом файл или группу переименуют - ничего не сломается. Если на файл сделают симлинк и будут обращаться через него - тоже ничего не сломается.

firkax ★★★★★
()
Ответ на: комментарий от firkax

В теории оно хорошо, но как это сделать на практике? Во-первых, объектом управления у нас является systemd, а не юнит-файл. Т.е. нам надо перехватывать внутреннюю логику systemd. Например, так сделано через PolicyKit, которая вызывается с уже нормализованными параметрами. ТС мог бы написать так:

polkit.addRule(function(action, subject) {
    if (subject.user == "user"
        && action.id == "org.freedesktop.systemd1.manage-units"
        && action.lookup("unit") == "userservice.service") {
        return polkit.Result.YES;
    }
});

И получил бы тот же результат без sudo*. Но этот способ всё равно предполагает, что мы не будем менять имя юнита и делать на него симлинки. Плюс, для конечного пользователя это всё равно сопоставление атрибутов с атрибутами, а значит, потенциально может быть дырой.

Второй вариант, это когда сам systemd проверяет расширенные атрибуты файла на предмет нахождения там гипотетической строки типа user=start,stop,restart. Что-то наподобие linuxcap или selinux. Такой подход имеет другую проблему, в полной мере продемонстрированную как раз selinux, которую многие не понимают, боятся и отключают. Почему? Потому что ничего не видно. Ты делаешь ls -l userservice.service и видишь там базовые права, а расширенных не видишь. А они есть. И очень легко получить, что пользователь как-то (через уязвимость, например) выдал себе права, а администратор не заметил. Упс.

И наконец, дискреционная модель доступа не обладает такой степенью гранулярности, которую можно получить через sudo. А что если сисадмин хочет дать пользователю возможность выбирать из трёх заранее заготовленных конфигураций перед рестартом? Через sudo это легко — выдать права на /bin/cp /opt/user-services-for-user1/userservice1.service /etc/systemd/system/userservice.service, и так три раза. А как это сделать через права на объект? Можно сделать три разных объекта, но куда девать зависимости?

Так что в теории, всё это хорошо и правильно, а на практике мы пользуемся sudo, потому что работать надо. Или ты можешь предложить какой-то правильный механизм, который я не заметил.

* - на самом деле не тот же, но мне лень разбираться с документаций и заодно хорошо показать безрассудство подхода. Я разрешил любые операции с юнитом :-)

Aceler ★★★★★
()