Короткий ответ

Неиспользуемая интерактивная учётка — сначала блокировка (passwd -l, usermod -s /usr/sbin/nologin), снятие ключей и cron, исключение из sudo/docker, затем userdel когда файлы и UID ничьи. Не userdel -r вслепую на mysql/www-data. Не чистите «всё с UID≥1000» скриптом без таблицы. Хост host.example (10.0.20.10), живой админ admin не трогать.

Симптомы и как отличить

  • lastlog Never logged in у людей, которые «работали год»;
  • chage -l ivan срок истёк, SSH ключом всё ещё входит;
  • дубли ubuntu, linuxuser с облачного образа.
ТипПримерыДействие
system UID < 1000www-data, systemd-timesyncне удалять
интерактивivan, adminинвентарь HR
сервисный ≥1000myserviceоставить

Полный проход команд — аудит пользователей. Ключи: отзыв. sudo: NOPASSWD.

Возможные причины

  1. Нет offboarding.
  2. Общая учётка admin + персональные, персональные забыли.
  3. GitLab runner user после миграции.
  4. adduser для теста.
  5. LDAP/sssd кэш локальных дублей (локальный passwd vs домен — не смешивайте удаление).

Диагностика

getent passwd | awk -F: '$3>=1000 {print $1,$3,$7}'
lastlog -b 90
sudo passwd -S -a | awk '$2!="L" && $2!="NP"'

passwd -S: P пароль, L lock, NP нет пароля.

sudo grep -R ivan /etc/sudoers /etc/sudoers.d/ /etc/group /etc/cron.d /var/spool/cron/crontabs 2>/dev/null
sudo ls -la /home/ivan/.ssh/ 2>/dev/null
sudo crontab -u ivan -l 2>/dev/null
id ivan

Процессы:

ps -u ivan
sudo lsof -u ivan 2>/dev/null | head

Решение

Сценарий A. Человек ушёл, учётка локальная

sudo passwd -l ivan
sudo usermod -s /usr/sbin/nologin ivan
sudo gpasswd -d ivan sudo 2>/dev/null || true
sudo gpasswd -d ivan docker 2>/dev/null || true
sudo crontab -u ivan -r 2>/dev/null || true
sudo mv /home/ivan/.ssh/authorized_keys /root/retired-ivan-keys.$(date +%F) 2>/dev/null || true

Проверьте, что не входит:

ssh -o BatchMode=yes ivan@10.0.20.10 true; echo $?

Через окно хранения — архив home и:

sudo userdel -r ivan

Только если UID не в файлах сервисов (find /var /opt -user ivan).

Сценарий B. Облачный ubuntu пользователь

Если вход только admin — заблокируйте ubuntu так же, ключи из /home/ubuntu/.ssh. Не оставляйте passwordless sudo cloud-init навсегда.

Сценарий C. Сервисная учётка «не логинилась»

lastlog Never для myservice — норма. Не блокируйте, если unit User=myservice. Смотрите systemctl grep User=.

Сценарий D. Общий admin, персональный ключ

Не удаляйте UNIX admin. Удалите строку ключа уволенного из authorized_keys. Иначе «учётка жива» правильно, доступ лишний.

Включите следы: auditd.

Порядок offboarding, чтобы не запереть прод. 1) Снять ключ и заблокировать пароль. 2) Проверить ps/tmux/screen и loginctl. 3) Забрать sudo/docker. 4) Подождать SLA хранения. 5) userdel. Если ivan владеет crontab бэкапа — сначала перенесите job на backup/root с нормальными правами, иначе lock оставит дыру в RPO.

Общие учётки (deploy, admin): не удаляйте UNIX-имя. Чистите ключи и sudoers drop-in персоналий. В комментарии authorized_keys должен быть человек, не ubuntu@laptop. Без комментария — инвентаризация fingerprint vs ноутбуки.

at jobs: sudo atq / atrm. Забытый at от уволенного выполнится от его uid, даже после nologin, пока учётка не удалена. После userdel at может остаться в spool — проверьте /var/spool/cron/atjobs.

Почта /var/mail/ivan и forward: удалите .forward чтобы не утекала почта на личный ящик.

Доменные пользователи: локальный passwd -l ivan не поможет, если ivan из sssd. Блокируйте в AD/IPA и снимайте кэш sss_cache. На хосте проверьте getent passwd ivan после блокировки в каталоге.

Не используйте chage -E 1970-01-01 как единственный метод при живых ключах — те же грабли, что passwd -l. Shell nologin + пустой authorized_keys обязательны.

Запись в тикете HR: дата lock, дата userdel, архив home путь. Без этого через год «можно удалить?» никто не знает.

Домашние каталоги после lock: chmod 750 /home/ivan чтобы коллеги не читали остатки ключей, пока home не архивирован. Не 000 — сломаете backup агент, если он ходит как тот же uid.

nologin текст в /etc/nologin — глобальный запрет интерактива для всех не-root, не путать с shell пользователя. Не кладите /etc/nologin случайно.

Сервисные UID, которые «давно не логинились», не трогайте пачкой вместе с людьми. Ориентир: наличие User= в unit, home в /var/lib, shell nologin. Скрипт «lock всех Never lastlog» убьёт myservice и postgres.

Ключи в /etc/ssh/authorized_keys или AuthorizedKeysFile с абсолютным путём — тоже снимите для уволенного, не только ~/.ssh.

Не удаляйте nobody/nogroup — это пакетные. Только UID≥1000 из HR-контура и явно тестовые adduser.

Как проверить, что проблема устранена

lastlog -b 90
sudo passwd -S ivan 2>/dev/null || echo 'no ivan'
getent passwd ivan || echo 'removed'
sudo grep -R ivan /etc/sudoers /etc/sudoers.d/ || echo 'no sudo'
ssh -o BatchMode=yes admin@10.0.20.10 true

HR-список совпадает с интерактивными UID≥1000. Сервисы живы. admin входит.

Если не помогло

  • Вход по ключу после passwd -l: не сняли authorized_keys / AuthorizedKeysCommand LDAP.
  • userdel «user is currently logged in»: loginctl terminate-user.
  • UID в ACL файлов — find -nouser.
  • sssd: удаляйте в каталоге, не только локально.
  • Заблокировали admin — консоль, passwd -u с root.

Профилактика

  • Чеклист увольнения: UNIX, ключи, sudo, docker, cron, VPN.
  • Квартальный lastlog.
  • Запрет общих интерактивных учёток кроме break-glass.
  • Baseline.

FAQ

passwd -l vs usermod -L

На Ubuntu passwd -l стандарт для lock пароля. Shell nologin — второй слой.

Можно ли сразу userdel

После lock и проверки процессов/файлов. Home — по политике хранения.

NP в passwd -S у admin

Ключи без пароля UNIX: sudo может не спросить если NOPASSWD. Всё равно нужен пароль консоли или другой break-glass.

UID 0 кроме root

awk -F: '$3==0' — только root. Второй uid 0 — инцидент.

nologin vs false

Оба не интерактивны. Пакетный /usr/sbin/nologin предпочтителен.