Пользователи, группы и sudo¶
Каждый файл, процесс и сокет в Linux принадлежит числовому ID пользователя и ID группы. Имена вроде alice или docker — только метки, которые ищутся в базе. Понимание этой базы и того, как sudo решает, кому можно действовать от имени root, лежит в основе прав доступа, SSH, служебных учётных записей и почти любой ошибки «permission denied».
О выводе на этой странице
Вывод id, stat, visudo -V и getent снят на Ubuntu 22.04 (sudo 1.9.9). Вывод команд, изменяющих учётные записи (useradd, usermod, gpasswd), приведён как пример с выдуманным пользователем alice: этим командам нужен root, и для статьи они не запускались.
Как это устроено¶
Идентичность — это число¶
Ядро знает только ID пользователя (UID) и ID групп (GID). id показывает их все для текущей сессии:
uid=1000(alice)— пользователь. UID 0 — это root, единственный UID, который ядро считает привилегированным.gid=1000(alice)— основная группа. Новые файлы получают эту группу.groups=...— дополнительные группы. Доступ разрешён, если совпала любая из них.
По соглашению UID ниже 1000 (порог — UID_MIN в /etc/login.defs) принадлежат системным и служебным учётным записям, а обычные люди начинаются с 1000.
Где хранятся учётные записи¶
| Файл | Содержимое | Обычные права |
|---|---|---|
/etc/passwd | Строка на пользователя: name:x:UID:GID:comment:home:shell | -rw-r--r-- (читается всеми) |
/etc/shadow | Хеши паролей и поля срока действия | -rw-r----- root:shadow |
/etc/group | Группы и их участники | -rw-r--r-- |
/etc/sudoers, /etc/sudoers.d/* | Кто какие команды может запускать через sudo | -r--r----- root:root |
Символ x в поле пароля /etc/passwd означает «хеш лежит в /etc/shadow». Разделение нужно потому, что /etc/passwd должен читаться всеми (программы сопоставляют UID с именами), а хеши — нет.
Не разбирайте эти файлы вручную в скриптах. Используйте getent: он идёт по той же цепочке поиска, что и остальная система (/etc/nsswitch.conf), и поэтому находит также пользователей из LDAP, SSSD и других источников:
getent passwd alice # alice:x:1000:1000:Alice:/home/alice:/bin/bash
getent group sudo # sudo:x:27:alice
Создание пользователей и управление группами¶
sudo useradd -m -s /bin/bash alice # -m создаёт /home/alice, -s задаёт оболочку входа
sudo passwd alice # задать пароль интерактивно
sudo usermod -aG docker alice # ДОБАВИТЬ alice в группу docker
sudo gpasswd -d alice docker # убрать alice из docker
Ключ -a в usermod -aG важен: он значит append (добавить). См. предупреждение ниже.
В Debian и Ubuntu adduser alice — более удобная обёртка: она запрашивает пароль и копирует файлы из skeleton; useradd — низкоуровневый инструмент, доступный в любом дистрибутиве.
Изменение групп не применяется к уже открытым сессиям. Процесс получает список групп при входе, поэтому alice должна выйти и войти снова (или запустить новую оболочку через newgrp docker), чтобы новая группа заработала. id в старой сессии по-прежнему показывает старый список. Это обычная причина ситуации «добавил себя в группу, а доступа всё равно нет».
Как sudo принимает решение¶
sudo — программа с setuid-root (-rwsr-xr-x root:root /usr/bin/sudo). Когда вы запускаете sudo command, она читает правила sudoers, проверяет, разрешено ли вашему пользователю или одной из ваших групп запускать эту команду от целевого пользователя, спрашивает ваш собственный пароль (не root), если правило не говорит иное, и запускает команду.
Правило sudoers выглядит так:
Первая строка читается так: пользователь alice на любом хосте (ALL) может запускать любые команды от любого пользователя и группы. Знак % в начале означает группу, поэтому вторая строка даёт те же права всем участникам группы sudo. В этом весь механизм «добавьте пользователя в группу sudo»:
- Debian и Ubuntu поставляют
%sudo ALL=(ALL:ALL) ALLв/etc/sudoers. - В RHEL-подобных системах то же правило задано для группы
wheel.
Узкие правила лучше, чем ALL:
# /etc/sudoers.d/deploy
deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart myapp, /usr/bin/systemctl status myapp
Всегда редактируйте через visudo, а не обычным редактором: он блокирует файл и проверяет синтаксис перед сохранением. Для drop-in файла: sudo visudo -f /etc/sudoers.d/deploy. Проверка без редактирования:
Что разрешено пользователю, смотрите через sudo -l (для себя) или sudo -l -U alice (от root).
Различия Ubuntu/Debian и RHEL-подобных систем¶
| Ubuntu/Debian | RHEL-подобные | |
|---|---|---|
| Группа администраторов | sudo | wheel |
| Удобный инструмент | adduser / deluser | только useradd / userdel |
| Учётная запись root | В Ubuntu по умолчанию заблокирована (используйте sudo -i); Debian при установке запрашивает пароль root, если его не оставили пустым | Пароль root обычно задаётся при установке |
| Права домашнего каталога | /home/user — 0750 в свежих Ubuntu | 0700 |
Поэтому добавление в группу администраторов выглядит как usermod -aG sudo alice в Debian/Ubuntu и usermod -aG wheel alice в RHEL-подобных системах.
Практическое задание¶
Выполняйте на одноразовой виртуальной машине, а не на рабочем сервере.
- Создайте пользователя и посмотрите записи:
- Добавьте
lab1в группу и проверьте: - Дайте
lab1узкое правило sudo, проверьте синтаксис и протестируйте: - Очистка:
Как проверить, что всё сделано правильно¶
- Шаг 1:
id lab1показываетuid=<n>(lab1) gid=<n>(lab1) groups=<n>(lab1), где<n>не меньше 1000. - Шаг 2:
id lab1теперь содержитlabgroupвgroups=. - Шаг 3:
visudo -cпечатаетparsed OKдля нового файла;sudo -u lab1 sudo -n idпечатаетuid=0(root)...; попыткаls /rootзавершаетсяsudo: a password is required(правило покрывает толькоid, а-nзапрещает запрос пароля). - Шаг 4:
getent passwd lab1иls /etc/sudoers.d/lab1ничего не находят.
Типичные ошибки¶
- Забыть, что смена групп требует нового входа. Работающая сессия хранит старый список групп.
- Легко выдавать членство в группе
docker. Любой участникdockerможет запустить контейнер с монтированием/и менять его от root, то есть группа равна root. Относитесь к ней как к sudo. - Терять окружение в
sudo.sudoпо замыслу сбрасывает большинство переменных окружения; если команде нужна переменная, передайте её явно (sudo VAR=value cmd), а не отключайтеenv_reset. - Неверные права у drop-in файла sudoers. Файлы в
/etc/sudoers.d/не должны быть доступны на запись группе или остальным (используйте0440), иначе sudo их игнорирует или отвергает. - Точка или тильда в имени файла в
/etc/sudoers.d/. Механизм include пропускает файлы с.в имени и заканчивающиеся на~, поэтомуdeploy.confможет молча ничего не делать.
⚠ Опасные команды¶
usermod -G docker alice(без-a) заменяет все дополнительные группы. Еслиaliceбыла вsudo, она только что потеряла права администратора; если это была единственная административная учётная запись, вы можете остаться без привилегированного доступа. Всегда используйте-aG.- Редактирование
/etc/sudoersнапрямую черезnano/vim. Одна синтаксическая ошибка — иsudoперестаёт работать у всех. Всегдаvisudo; при смене правил держите открытым root-шелл в другом терминале. NOPASSWD: ALLдля человека или любое правило, разрешающее оболочку, редактор илиless(они запускают шелл): это неограниченный root без запроса пароля. Разрешайте точные команды.userdel -rудаляет домашний каталог без возможности отмены. Сначала сделайте резервную копию и убедитесь, что у учётной записи нет работающих процессов (pgrep -u alice).- Удаление или перенумерация UID 0 и системных учётных записей. Не меняйте UID существующего пользователя, не исправив владельца всех его файлов (
find / -xdev -uid <старый> -exec chown ...).
Связанные статьи¶
- Иерархия файловой системы Linux, права и владельцы: владельцы и биты прав
- Харденинг SSH и аутентификация по ключам: ключи пользователей и кто может входить
Контрольные вопросы¶
- Что на самом деле использует ядро для решения о доступе — имена или числа? Откуда берутся имена?
- Почему
usermod -Gбез-aможет оставить вас без доступа? - Вы добавили пользователя в группу, но
idв его открытом терминале её не показывает. Почему? - Какая команда проверяет синтаксис sudoers, пока он не сломал
sudoу всех? - Почему членство в группе
dockerфактически равно доступу root?