MAATRIX / Блог / Ревизия доступов раз в квартал: кто до сих пор может зайти на ваш сервер

Ревизия доступов раз в квартал: кто до сих пор может зайти на ваш сервер

MAATRIX

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

Почему доступы накапливаются сами по себе

Проблема не в разгильдяйстве конкретного админа — она системная. Выдать доступ почти всегда легче и быстрее, чем его отозвать, а стимул отозвать появляется только тогда, когда об этом кто-то вспомнит. За обычный квартал в компании из 10-15 человек, работающей с внешними серверами, накапливаются как минимум три типа мусора.

Во-первых, доступы уволенных сотрудников. Формальный офбординг обычно покрывает то, что видно сразу: корпоративную почту, Slack, доступ в офис. SSH-ключ в ~/.ssh/authorized_keys на сервере, который человек сам себе когда-то добавил, туда не входит — просто потому что о нём никто, кроме самого сотрудника, не знает. Реальный случай, который встречается чаще, чем кажется: ключ уволенного сотрудника продолжает работать месяцами, потому что никто не составлял список серверов, куда у него был доступ — разбор одного такого случая есть отдельно.

Во-вторых, доступы подрядчиков. Фрилансер настраивал CI/CD, агентство делало редизайн, консультант чинил производительность базы — у каждого на время проекта был root или как минимум доступ к части инфраструктуры. Проект закрылся, счёт оплачен, но ключ в authorized_keys остался: отзыв доступа не входит в чек-лист закрытия проекта, потому что чек-листа закрытия проекта часто просто нет.

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

Что входит в ревизию: карта всех точек доступа

Прежде чем сверять списки, нужно понять, что вообще считать «доступом». Узкое понимание — только SSH на серверы — пропускает большую часть реального риска. Полная карта точек доступа для типичной инфраструктуры на аренде VPS или выделенных серверов выглядит так:

  • SSH-доступ на серверы — ключи в authorized_keys, пользователи с sudo, доступ по паролю (если ещё не отключён).
  • Панели управления — панель хостинг-провайдера, DNS-регистратор, CDN, панель email-рассылок.
  • VPN и туннели — конфиги WireGuard/OpenVPN, у кого какие peer'ы всё ещё активны.
  • Репозитории кода — организация на GitHub/GitLab, кто состоит в командах с правом push в прод-ветки.
  • CI/CD и секреты — кто имеет доступ к переменным окружения в пайплайнах, к Vault или другому хранилищу секретов.
  • Базы данных — прямые учётки на постгрес/MySQL, отдельно от доступа на уровне ОС.
  • Мониторинг и логи — доступ к Grafana, Prometheus, системам алертинга (сам по себе не критичен, но часто открывает вид на внутреннюю топологию).
  • Общие пароли — то, что когда-то скинули в чат или менеджер паролей и с тех пор не меняли.

Для маленькой инфраструктуры (2-5 серверов) весь этот список можно держать в одной таблице. Для инфраструктуры покрупнее имеет смысл завести реестр в виде YAML или простой базы — критично не то, в каком формате, а то, что реестр вообще существует и обновляется при каждой выдаче доступа, а не восстанавливается по памяти раз в квартал.

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

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

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

Шаг 1: собрать полный список — кто и куда имеет доступ

Ревизия начинается не со сверки, а со сбора актуальных фактов с самих серверов — потому что реестр (если он есть) почти наверняка успел разойтись с реальностью. Если у вас есть инвентарь серверов (Ansible, Terraform-стейт или просто список хостов), пройдитесь по нему скриптом:

#!/usr/bin/env bash
# audit_access.sh — собрать SSH-ключи и sudo-пользователей со всех серверов
while read -r host; do
  echo "== $host =="
  ssh -o ConnectTimeout=5 "$host" '
    echo "--- authorized_keys по пользователям ---"
    for u in $(cut -d: -f1 /etc/passwd); do
      home=$(getent passwd "$u" | cut -d: -f6)
      if [ -s "$home/.ssh/authorized_keys" ]; then
        echo "[$u]"
        awk "{print \$NF}" "$home/.ssh/authorized_keys"
      fi
    done
    echo "--- sudo/wheel ---"
    getent group sudo wheel 2>/dev/null
  '
done < inventory.txt

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

Отдельно выгрузите доступ из внешних сервисов — там всё проще, потому что почти везде есть список участников в UI или API:

# GitHub: список участников организации с ролями
gh api orgs/YOUR_ORG/members --paginate | jq -r '.[].login'

# WireGuard: активные peer'ы на сервере
sudo wg show wg0 peers

# Postgres: список ролей с правом логина
psql -c "SELECT rolname, rolcanlogin, rolsuper FROM pg_roles WHERE rolcanlogin;"

Для панелей хостинга и DNS-регистраторов автоматического способа обычно нет — там просто открываете раздел «Пользователи» или «Команда» и выписываете список руками. Это единственный трудоёмкий, но короткий по времени шаг: на 3-5 внешних панелей уходит 15-20 минут.

Шаг 2: сверить список с реальными людьми

Собранный список доступов сам по себе ничего не говорит — его нужно сопоставить с эталоном: кто сейчас реально работает в компании и с кем сейчас есть действующий договор подряда. Источник истины здесь — не память, а два конкретных списка:

  • Актуальный список сотрудников из HR-системы или, если её нет, из последней ведомости/списка на зарплату.
  • Список подрядчиков с активными договорами — если договор закрыт или истёк, подрядчик выбывает из списка независимо от того, насколько хорошо он работал.

Сверка — это буквально diff двух списков:

# access_list.txt — кто имеет доступ (по данным шага 1)
# active_people.txt — кто сейчас в команде и по действующим договорам
sort access_list.txt -o access_list.txt
sort active_people.txt -o active_people.txt
diff access_list.txt active_people.txt

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

На этом шаге удобно завести простую таблицу для итогов ревизии:

КтоГде доступСтатусДействие
ivan.petrovsrv-db-01, GitHub orgуволен 3 мес. назадотозвать всё
agency-xsrv-web-02 (root)проект закрыт в июнеотозвать SSH-ключ
test_deploysrv-web-01 (sudo)тестовая учётка, автор неизвестенуточнить, затем удалить
maria.kwg0 peerактивный сотрудникоставить

Шаг 3: отозвать лишнее, ничего не сломав

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

Первое: не привязан ли этот доступ к работающему процессу. Ключ с комментарием ci-deploy@github-actions выглядит как бесхозный, но это может быть сервисный аккаунт, через который заезжает деплой. Прежде чем удалять — найдите, где именно этот ключ используется (grep по конфигам CI/CD, поиск по имени пользователя в cron и systemd-таймерах), и либо перевыпустите ключ на новый сервисный аккаунт, либо явно задокументируйте, что он служебный и остаётся.

Второе: отзывайте по возможности сразу, а не «пакетом в конце квартала». Между обнаружением лишнего доступа и его отзывом — минуты, не дни: чем длиннее список найденных проблем, тем больше шанс, что часть из них забудут закрыть до следующей ревизии.

Практический порядок отзыва:

# Удалить конкретный ключ из authorized_keys (по последним 20 символам ключа)
sed -i '/AAAAB3NzaC1yc2EAAAADAQABAAAB...XXXX/d' ~/.ssh/authorized_keys

# Заблокировать системного пользователя без удаления (сохраняет владельца файлов)
sudo usermod -L -s /usr/sbin/nologin ivan.petrov

# Отозвать доступ в GitHub-организации
gh api -X DELETE orgs/YOUR_ORG/members/username

# Удалить peer из WireGuard
sudo wg set wg0 peer <PUBLIC_KEY> remove
sudo wg-quick save wg0

Для панелей и внешних сервисов, где нет API или CLI, — обычная деактивация через UI, но обязательно с отметкой в реестре (кто отозвал, когда, на основании чего), иначе следующая ревизия снова начнётся с нуля. Если в компании уже случалась ситуация, когда ключ подрядчика годами лежал в authorized_keys невостребованным, порядок разбора такого случая — в отдельной статье про аудит ключа подрядчика за час.

Как сделать ревизию рутиной, а не подвигом

Одна ревизия, сделанная героическим усилием после инцидента или тревожной мысли в три часа ночи, закрывает накопленный долг один раз. Без превращения её в регулярную процедуру долг начнёт копиться заново со следующего дня. Три вещи делают ревизию устойчивой.

Фиксированная дата и владелец. Квартальная ревизия должна быть привязана к календарю (первая неделя января/апреля/июля/октября, например), а не к «когда вспомним». У процедуры должен быть конкретный ответственный — не «кто-то из команды», а один человек, у которого это в списке задач и с которого можно спросить.

Реестр доступов, который живёт постоянно, а не восстанавливается заново. Если каждая выдача доступа — будь то новый сотрудник, подрядчик на проект или временная тестовая учётка — сразу попадает в общий список с датой и причиной, ревизия превращается из расследования в 20-минутную сверку. Формат реестра почти не важен: подходит простой YAML-файл в приватном репозитории, таблица в Notion или Google Sheets — важно, что в него пишут по умолчанию, а не по желанию. О том, как выстроить этот процесс с нуля для новых сотрудников, — в статье про оформление доступа сотрудников к продакшену.

Правило автоматического истечения для временных доступов. Доступ подрядчика или временного сотрудника изначально стоит выдавать с датой окончания, а не бессрочно. Это можно сделать формально (cron-задача, которая раз в неделю сверяет даты в реестре с текущей и присылает напоминание) или хотя бы вручную — но обязательно с явной датой в календаре того, кто выдавал доступ. Такая практика снимает большую часть работы будущей ревизии: если доступ подрядчика и так должен был закончиться, ревизия просто подтверждает факт, а не открывает новый.

Для контроля между ревизиями полезно завести лёгкий мониторинг: скрипт раз в неделю сверяет текущий список authorized_keys на серверах с зафиксированным в реестре и присылает уведомление о расхождении. Это не заменяет квартальную ревизию — расхождение может быть легитимным (новый сотрудник ещё не занесён в реестр), — но сокращает разрыв между появлением нового доступа и моментом, когда о нём кто-то узнаёт.

Что проверить в первую очередь, если ревизии никогда не было

Если это первая ревизия за всё время существования инфраструктуры, не пытайтесь сразу построить идеальный процесс — сначала закройте наиболее вероятные риски. Порядок приоритета:

  1. Серверы с прямым доступом к деньгам или персональным данным клиентов — платёжные интеграции, база пользователей, бэкапы.
  2. SSH-ключи и sudo-права — они дают самый прямой и самый долгоживущий доступ.
  3. Панель хостинг-провайдера и DNS-регистратор — потеря контроля здесь означает потенциальную потерю всей инфраструктуры, а не одного сервера.
  4. Репозитории кода с правом push в защищённые ветки.
  5. Всё остальное — мониторинг, аналитика, второстепенные сервисы.

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

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

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

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

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

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

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

Раз в квартал — не слишком редко? Может, нужно чаще?

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

Что делать, если реестра доступов никогда не было и восстановить историю невозможно?

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

Нужно ли уведомлять человека, у которого отозвали доступ?

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

Как быть с сервисными аккаунтами и ключами для автоматизации — их тоже ревизировать?

Да, и даже внимательнее, чем личные доступы: сервисный ключ обычно шире по правам и служит дольше, потому что никто не увольняется вместе с cron-задачей. Проверяйте, что каждый сервисный ключ до сих пор используется реальным процессом, а не остался от давно отключённой интеграции.

Что делать с общими паролями (root-пароль от панели, общий доступ к БД), которые знают все?

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

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

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

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