MAATRIX / Блог / Сотрудник уволился: где остались его файлы, ключи и доступы

Сотрудник уволился: где остались его файлы, ключи и доступы

MAATRIX

Отзыв учётных записей после увольнения — это только вершина айсберга. Сотрудник, который два-три года администрировал инфраструктуру или писал код, почти гарантированно оставил после себя личные файлы вне общих папок, ключи, добавленные вручную мимо централизованной системы, и токены, выпущенные лично на его имя в десятке сервисов. Ни один из этих следов не виден в списке «активных пользователей» — их нужно искать целенаправленно, и ниже разобрано, где именно.

Почему это не то же самое, что отзыв доступов

Отзыв доступа — это удаление учётной записи, блокировка входа, отзыв токена в интерфейсе сервиса. Это нужный, но формальный шаг: он убирает возможность зайти под своим именем. Он не убирает данные, которые человек уже успел оставить — файлы на диске сервера, ключи, вписанные в чужие конфигурации, копии секретов в его личных скриптах.

Разница принципиальная. Если вы заблокировали учётку в GitLab, но у бывшего сотрудника на рабочем ноутбуке остался клон репозитория с закешированным .env-файлом — доступ формально отозван, а копия данных жива. Если вы удалили его из списка пользователей на сервере через userdel, но не тронули /home/ivan с флагом --remove — домашняя папка с историей команд, приватными ключами и черновиками конфигов останется лежать на диске бессрочно.

Эта статья — не про то, как отозвать доступ (об этом порядке действий на один вечер — в статье сотрудник уволился, а доступ остался: аудит за один вечер), а про то, что физически остаётся на серверах и в сервисах после того, как доступ уже отозван. Это отдельная задача, и у неё нет автоматического решения — нужно систематически пройтись по местам, где сотрудник мог оставить след.

Личные файлы на рабочих серверах вне общих папок

Любой человек, который регулярно заходит на сервер по SSH, рано или поздно заводит там что-то своё — не по злому умыслу, а потому что удобнее держать под рукой. Проблема в том, что это «своё» никто не документирует, и после увольнения оно просто лежит мёртвым грузом, иногда с чувствительным содержимым.

Где искать в первую очередь:

  • Домашняя директория пользователя. /home/username — самое очевидное место, но проверяют его не всегда полностью: заглядывают в корень, а не рекурсивно. Внутри часто находятся черновики скриптов, конфиги с паролями «на всякий случай», дампы БД, скачанные для локальной отладки, и файл .bash_history с командами, которые он вводил.
  • Временные директории. /tmp и /var/tmp не чистятся автоматически на всех дистрибутивах (systemd-tmpfiles по умолчанию трогает не всё, а на старых системах и вовсе не настроен), и файлы, положенные туда полгода назад, вполне могут пережить увольнение.
  • Директории вне стандартных путей. Если у сотрудника был root или широкий sudo, он мог создать директорию где угодно — /opt/ivan-scripts, /srv/backup-ivan, даже /root/tmp. Единого способа найти всё это нет, кроме целенаправленного поиска по владельцу файла.

Практическая команда — найти всё, что принадлежит конкретному пользователю, по всей файловой системе:

# ищем все файлы, принадлежащие uid уволенного сотрудника
find / -xdev -user ivan -not -path "/proc/*" 2>/dev/null

Если аккаунт уже удалён, а UID неизвестен — посмотрите его в бэкапе /etc/passwd (если он делается) или в логах аудита, либо ищите по времени последней активности:

# файлы, изменённые за последние 90 дней его работы (пример диапазона)
find /home /opt /srv /tmp /var/tmp -newermt "2026-05-01" ! -newermt "2026-08-25" -type f 2>/dev/null

Отдельно проверьте, не остались ли смонтированные сетевые ресурсы или примонтированные бэкапы, к которым он подключался вручную (mount без записи в /etc/fstab, временные NFS/SMB-подключения) — команда mount | grep -v -f /etc/fstab покажет то, что смонтировано, но не описано в постоянной конфигурации.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

SSH-ключи, добавленные лично в обход централизованной системы

Даже если в компании внедрена централизованная раздача ключей (Ansible, Teleport, свой internal CA для SSH-сертификатов), почти всегда находится сервер, куда ключ был добавлен руками — потому что «нужно было быстро», «этого сервера ещё не было в инвентаре» или «это тестовый стенд, зачем городить автоматику». Именно такие ключи и остаются забытыми: разбор реального случая, когда такой ключ проработал восемь месяцев после увольнения, — в статье SSH-ключ уволенного сотрудника работал восемь месяцев.

Проверка должна идти не только по серверам из официального инвентаря, а по всем, до которых можно дотянуться:

#!/usr/bin/env bash
# для каждого сервера из inventory.txt выводим все authorized_keys
while read -r host; do
  echo "== $host =="
  ssh -o BatchMode=yes -o ConnectTimeout=5 "$host" \
    "sudo find / -xdev -name authorized_keys -exec cat {} \; 2>/dev/null"
done < inventory.txt

Обратите внимание на три места, которые часто пропускают при беглой проверке:

  • AuthorizedKeysFile с нестандартным путём — если в /etc/ssh/sshd_config указан не .ssh/authorized_keys, а что-то вроде /etc/ssh/authorized_keys/%u, обычный поиск по домашним директориям ключ не найдёт.
  • Legacy-путь authorized_keys2 — часть старых конфигураций sshd до сих пор его читает, хотя новые ключи туда никто не добавляет намеренно.
  • Ключи, раскатанные автоматикой из чужого источника правды. Если ключ сотрудника был один раз вписан в Ansible-плейбук или Terraform-модуль, удаление вручную с сервера ничего не решит — при следующем прогоне автоматики ключ вернётся. Нужно найти и убрать сам источник в репозитории конфигурации.

Идентифицировать владельца найденного ключа, если он не подписан явно, помогает fingerprint — сравните с тем, что известно о сотруднике по его рабочей машине или по записи в централизованной системе (если её вели):

ssh-keygen -lf <(echo "ssh-ed25519 AAAA... ivan@ivan-laptop")

Если найден ключ без явного комментария-имени, а инвентаря владельцев никогда не было — сопоставьте по времени добавления (stat authorized_keys покажет дату модификации файла) с датой найма или последнего изменения инфраструктуры, которую делал именно этот сотрудник.

Персональные API-токены и ключи, выпущенные на его имя

Токены — самая незаметная категория среди всех, потому что большинство сервисов не показывают список активных токенов на первом экране, а некоторые вообще не отзывают их автоматически при удалении пользователя из организации.

Систематически стоит пройтись по категориям сервисов, где токены обычно выпускаются персонально:

Категория сервисаЧто искатьГде проверять
Облачные провайдеры и хостингAccess key / API-ключ личного кабинетаIAM / раздел API-ключей в панели
CI/CDPersonal access token для пайплайновНастройки пользователя в GitLab/GitHub/Jenkins
Мониторинг и алертингAPI-ключ для чтения метрик или управления алертамиGrafana, Zabbix, PagerDuty — раздел API keys
DNS и CDNТокен на управление зоной или кешемЛичный кабинет регистратора, панель CDN
Мессенджеры и ботыТокен Telegram-бота, вебхук Slack@BotFather, настройки интеграций Slack
Платёжные и биллинговые системыAPI-ключ на чтение транзакцийПанель платёжного шлюза

Ключевая проблема этой категории в том, что токен продолжает работать даже после удаления учётной записи в интерфейсе — если сервис не связывает жизненный цикл токена с жизненным циклом пользователя. Не полагайтесь на интерфейс, проверяйте фактическую работоспособность после отзыва:

curl -s -o /dev/null -w "%{http_code}\n" \
  -H "Authorization: token ghp_xxx" https://api.github.com/user
# ожидаем 401 — токен реально не работает

Отдельно проверьте личные скрипты и cron-задачи сотрудника (следующий раздел) на предмет захардкоженных токенов — если он подключал API через переменную окружения или файл конфига в своей домашней директории, эти значения нужно не просто удалить с сервера, а физически отозвать на стороне сервиса, потому что сам факт удаления файла не аннулирует ключ.

Если какой-либо из найденных токенов уже успел засветиться публично (в коммите, в логе сборки, в публичном gist) — это отдельная и более срочная ситуация, разбор того, что конкретно отзывать и как оценить масштаб, — в статье токен уехал в публичный репозиторий: что отзывать.

Локальные конфиги, cron-задачи и скрипты без документации

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

Проверьте персональные cron-задачи на каждом сервере из инвентаря — они хранятся отдельно от системных заданий в /etc/cron.d:

# crontab конкретного пользователя (если аккаунт ещё не удалён)
crontab -l -u ivan

# все персональные crontab на сервере разом
for u in $(cut -f1 -d: /etc/passwd); do
  echo "== $u =="; crontab -l -u "$u" 2>/dev/null
done

Отдельно проверьте systemd-таймеры и юниты, запущенные от имени конкретного пользователя, — они не всегда попадают в поле зрения при беглом аудите, потому что визуально выглядят как «системные»:

systemctl list-timers --all
systemctl list-units --type=service | grep -i ivan
grep -rl "User=ivan" /etc/systemd/system/

Проверьте также запущенные процессы и файлы, которые всё ещё держит открытыми учётная запись — иногда демон или screen/tmux-сессия продолжает работать даже после блокировки логина:

ps -u ivan
lsof -u ivan

Отдельная категория — недокументированные скрипты в общих директориях (/opt, /usr/local/bin, репозиторий с инфраструктурным кодом), которые сотрудник написал и которыми пользовался только он: деплой-скрипты с захардкоженными путями и учётными данными, обвязка вокруг бэкапов, самописные утилиты мониторинга. Найти такие скрипты можно по владельцу файла и по отсутствию упоминаний в документации:

find /opt /usr/local/bin /usr/local/sbin -type f -user ivan 2>/dev/null

Каждый найденный скрипт нужно прочитать перед удалением — если он реально выполняет полезную функцию (например, единственный существующий механизм ротации логов на этом сервере), его нужно не стереть, а передать в общий репозиторий и назначить нового ответственного, иначе вы рискуете сломать то, что незаметно держалось на этом человеке.

Чек-лист систематической проверки при увольнении

Полагаться на память — главная причина, по которой такие следы находят спустя месяцы, а не в день увольнения. Ниже — порядок, по которому стоит пройтись именно по данным и файлам (отзыв самих учётных записей — отдельный процесс, который должен идти параллельно или раньше):

  1. Составьте список серверов, на которые у сотрудника вообще был доступ. Источники: Ansible-инвентарь, Terraform-стейт, список арендованных VPS в личном кабинете хостинг-провайдера, история ~/.ssh/config на его рабочей машине (если она осталась в компании).
  2. На каждом сервере — поиск файлов по владельцу. find / -xdev -user <username> плюс отдельная проверка /home/<username> рекурсивно, а не только на верхнем уровне.
  3. Проверка authorized_keys на каждом сервере, а не только на тех, что в официальном инвентаре. Включая нестандартные пути из AuthorizedKeysFile и legacy authorized_keys2.
  4. Инвентаризация персональных cron-задач и systemd-таймеров. crontab -l -u <username> на каждом сервере плюс grep по User= в юнитах systemd.
  5. Список активных API-токенов по каждому внешнему сервису. Облачный провайдер, CI/CD, мониторинг, DNS, боты — пройтись по разделу «API keys» или «Personal access tokens» в каждом, а не полагаться на то, что удаление пользователя из организации отозвало токены автоматически.
  6. Проверка личных скриптов в общих директориях. /opt, /usr/local/bin, репозитории с инфраструктурным кодом — найти файлы по владельцу, прочитать перед удалением, задокументировать то, что реально используется.
  7. Фиксация результата письменно. Даже короткая запись «проверено, найдено, устранено» по каждому серверу защищает от ситуации, когда через полгода кто-то снова тратит вечер на тот же аудит, потому что не уверен, делали его уже или нет.

Если такого списка серверов и сервисов в компании никогда не было — это тоже сигнал: без единого реестра доступов (как оформить доступ сотрудников к продакшену разбирает, как формально выстроить эту точку учёта) каждая проверка при увольнении будет неполной по определению, потому что вы физически не можете проверить сервер, о существовании которого не знаете.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Сколько времени реально занимает такая проверка на инфраструктуре из 10-15 серверов?

Если инвентарь серверов уже есть и команды из этой статьи прогоняются скриптом по списку — от двух до четырёх часов на первый полный проход. Без готового инвентаря время увеличивается в несколько раз, потому что первый шаг — составить сам список того, что нужно проверить.

Нужно ли удалять домашнюю директорию сотрудника сразу или сначала сохранить копию?

Сначала сохранить архивную копию (tar czf ivan-home-backup.tar.gz /home/ivan) в защищённое хранилище на разумный срок (например, 90 дней), и только потом удалять с сервера — это защищает от ситуации, когда в директории оказался единственный экземпляр чего-то нужного, о чём никто не вспомнил в первый день.

Что делать, если найденный скрипт или cron-задача явно выполняет важную функцию, но нигде не задокументирована?

Не удалять сразу — сначала выяснить, что произойдёт при остановке (по логам, по зависимым системам), затем перенести логику в общий репозиторий с документацией и назначить ответственного, и только после этого убирать оригинал с личными путями и учётными данными автора.

Как быть с личными файлами на корпоративном ноутбуке, а не на серверах?

Это отдельный процесс офбординга оборудования — обычно полная переустановка системы или как минимум смена всех локальных учётных данных, если ноутбук передаётся следующему сотруднику; сама статья фокусируется на серверной стороне, потому что там риск выше и следы менее заметны.

Стоит ли автоматизировать эту проверку, если увольнения случаются нечасто?

Даже нечастые увольнения стоит проверять по единому скрипту, а не руками каждый раз — риск не в частоте, а в том, что при разовой ручной проверке легко пропустить пункт, а скрипт, однажды написанный и сохранённый в репозитории, гарантированно проходит по всем пунктам одинаково.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →