MAATRIX / Блог / Регламент доступа подрядчика на сервер: выдали, ограничили, забрали

Регламент доступа подрядчика на сервер: выдали, ограничили, забрали

MAATRIX

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

Почему «выдали и забыли» — это системная проблема, а не случайность

Когда доступ подрядчику выдаёт человек, а не процесс, результат зависит от того, насколько этот человек торопится и насколько ему лень разбираться в тонкостях. В моменте всегда проще дать root и общий пароль от панели — это займёт минуту, а разбор, какие именно права нужны под задачу, займёт полчаса. Разница в полчаса на входе превращается в дни на разбор при аудите, потому что широкий доступ невозможно частично отозвать: либо оставляешь как есть, либо выкорчёвываешь заново, гадая, что именно ломать нельзя.

Три типовых провала, из которых складывается эта проблема:

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

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

Фаза 1: выдача — минимально необходимые права под конкретную задачу

Первый вопрос при любом запросе доступа — не "кому доверяем", а "что именно нужно для задачи". Формулировка задачи должна быть достаточно конкретной, чтобы из неё сразу следовал список прав, а не наоборот. "Настроить резервное копирование на сервере приложения" — это доступ к директориям с данными, к cron, возможно к S3-совместимому хранилищу бэкапов. Это не root, не доступ к базе данных с продовскими клиентами и не доступ к соседним серверам в сети.

Практический алгоритм на выдачу:

  1. Формулируется задача письменно — не устно по звонку, а в тикете или переписке, чтобы к формулировке можно было вернуться при отзыве.
  2. Из задачи выводится минимальный набор прав: конкретные директории, конкретные сервисы, конкретные команды через sudo, а не полный shell-доступ.
  3. Заводится отдельная именная учётная запись — никогда не общий пользователь deploy или admin, которым пользуются несколько человек.
  4. Фиксируется дата начала и плановая дата окончания — даже если срок ориентировочный, у доступа должна быть точка отсчёта.

На уровне Linux это выглядит примерно так — создание пользователя без интерактивного пароля, только с SSH-ключом, и с ограниченным sudo:

# Создать пользователя без пароля, вход только по ключу
useradd -m -s /bin/bash -c "Contractor: Ivan Petrov, task #1234" petrov_contractor
mkdir -p /home/petrov_contractor/.ssh
echo "ssh-ed25519 AAAA...контракторский-ключ..." > /home/petrov_contractor/.ssh/authorized_keys
chown -R petrov_contractor:petrov_contractor /home/petrov_contractor/.ssh
chmod 700 /home/petrov_contractor/.ssh
chmod 600 /home/petrov_contractor/.ssh/authorized_keys
passwd -l petrov_contractor

Sudo выдаётся не блоком ALL=(ALL) ALL, а точечным списком команд под задачу — например, если подрядчику нужно только перезапускать один сервис и читать его логи:

# /etc/sudoers.d/petrov_contractor
petrov_contractor ALL=(root) NOPASSWD: /usr/bin/systemctl restart myapp.service, /usr/bin/journalctl -u myapp.service *

Это не идеальная защита — при желании через дырявый sudo-скрипт можно эскалировать привилегии, поэтому команды в sudoers стоит выбирать осторожно и без широких масок вроде /usr/bin/systemctl * — но это на порядок лучше, чем открытый root, и резко сокращает то, что нужно проверять при офбординге. Если задача вообще не требует shell-доступа к серверу — например, только работа с API приложения или с админкой — доступ на уровне ОС подрядчику вообще не нужен, и об этой альтернативе стоит подумать в первую очередь, прежде чем заводить системного пользователя.

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

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

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

Фаза 2: ограничение на время работы — доступ только к тому, что реально нужно

Выдать точечные права один раз — необходимо, но недостаточно: за время работы задача часто "расползается", и подрядчик по ходу дела просит доступ то к соседнему серверу, то к базе, то к переменным окружения с чужими секретами. Каждое такое расширение нужно проводить как отдельное решение, а не как автоматическое "раз уж человек уже внутри".

Три конкретных ограничения, которые стоит закладывать сразу:

Сетевая изоляция. Подрядчик заходит не в общую сеть со всеми серверами компании, а туда, куда ему реально нужно. Если у вас есть jump host или bastion, ограничьте вход только через него, с логированием сессии:

# /etc/ssh/sshd_config на целевом сервере
Match User petrov_contractor
    AllowTcpForwarding no
    X11Forwarding no
    PermitTunnel no
    ForceCommand /usr/local/bin/restricted-shell.sh

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

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

# Отдельный лог sudo-действий по каждому пользователю
Defaults logfile="/var/log/sudo-petrov_contractor.log"
Defaults log_input, log_output

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

# Аккаунт автоматически блокируется 20 сентября 2026 года
chage -E 2026-09-20 petrov_contractor

Если задача может затянуться, это нормально — но продление должно быть таким же осознанным действием, как и выдача: новая дата, новое подтверждение, а не молчаливое "пусть повисит подольше на всякий случай".

Фаза 3: гарантированный отзыв — офбординг как часть закрытия проекта

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

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

  • [ ] Работа принята и подтверждена заказчиком
  • [ ] Проведена оплата или подписан акт
  • [ ] Отозван SSH-ключ подрядчика из authorized_keys
  • [ ] Учётная запись заблокирована или удалена
  • [ ] Отозваны выданные API-токены и ключи доступа к внешним сервисам
  • [ ] Закрыты временные правила firewall, открытые под задачу
  • [ ] Удалён доступ к репозиторию, если он выдавался отдельно от сервера
# Быстрый отзыв: заблокировать и убрать ключ
usermod -L petrov_contractor
> /home/petrov_contractor/.ssh/authorized_keys
# Если аккаунт больше не нужен вообще — удалить с домашней директорией
userdel -r petrov_contractor

Важно не полагаться только на память ответственного за проект — стоит завести напоминание или тикет с датой на день планового завершения задачи, который сработает, даже если про доступ забыли. Если у вас несколько подрядчиков параллельно, полезно вести отдельный реестр — таблицу или тикеты, где против каждой временной учётной записи стоит дата выдачи, дата планового отзыва и статус. Регулярная сверка этого реестра с реальным состоянием /etc/passwd и authorized_keys на серверах закрывает случаи, когда доступ забыли отозвать вручную — этому посвящена отдельная практика ревизии доступов раз в квартал, и связку с этим регламентом стоит выстроить с самого начала, а не добавлять постфактум.

Отдельно затронем частую ошибку: даже когда доступ формально отозван, забытыми часто остаются побочные следы — cron-задачи, оставленные от имени временного пользователя, ключи в CI/CD, добавленные "чтобы подрядчик мог задеплоить", записи в базе данных сервисных аккаунтов. Полный список того, что нужно проверить при закрытии за подрядчиком, разобран отдельно в статье «Подрядчик закончил работу: как закрыть за ним двери» — она хорошо дополняет этот регламент как чек-лист именно для фазы отзыва.

Регламент в виде документа: что зафиксировать письменно

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

Что фиксируетсяГде хранитсяКто отвечает
Заявка на доступ с формулировкой задачиТикет-система или перепискаЗаказчик задачи внутри компании
Список выданных прав и учётная записьВнутренний реестр доступовАдминистратор, выдавший доступ
Плановая дата отзываТот же реестр + напоминание/тикетЗаказчик задачи
Факт отзыва с датой и подтверждениемЧек-лист закрытия проектаАдминистратор + заказчик

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

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

Технические механизмы: как сделать ограничения неснимаемыми по умолчанию

Регламент на бумаге работает ровно до тех пор, пока его не забыли выполнить руками. Устойчивее — заложить ограничения так, чтобы они действовали технически, а не только процедурно:

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

ssh-keygen -s ca_key -I petrov_contractor -n petrov_contractor \
  -V +14d -O force-command="/usr/local/bin/restricted-shell.sh" \
  petrov_contractor_key.pub

Флаг -V +14d означает, что сертификат действует ровно 14 дней от момента выпуска и дальше не проходит проверку сервером — даже если про ручной отзыв забыли, доступ технически исчезнет сам.

Изоляция через контейнер или отдельную виртуалку. Если задача подрядчика по своей природе ограничена одним сервисом, часто разумнее не давать доступ к хост-системе вообще, а выдать доступ внутрь контейнера или отдельной VM, поднятой специально под задачу. Это radically сокращает площадь того, что нужно проверять при отзыве — вместо аудита прав на общем сервере просто удаляется весь контейнер целиком.

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

#!/bin/bash
# /usr/local/bin/check-contractor-access.sh
TODAY=$(date +%s)
while IFS=, read -r user expiry; do
  EXP_TS=$(date -d "$expiry" +%s)
  if [ "$TODAY" -gt "$EXP_TS" ] && id "$user" &>/dev/null; then
    echo "ВНИМАНИЕ: $user просрочен с $expiry, но аккаунт активен" | mail -s "Просроченный доступ подрядчика" admin@example.com
  fi
done < /etc/contractor-access-registry.csv

Ни один из этих механизмов не заменяет процесс целиком — сертификат с истёкшим сроком не удаляет остатки в cron или CI, а скрипт-напоминание не сработает, если реестр не обновляли. Но вместе они переводят отзыв доступа из категории "нужно не забыть" в категорию "сработает само, если не остановить" — а это ровно та разница, которая на практике решает, будет доступ висеть месяцами или закроется вовремя.

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

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

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

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

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

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

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

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

Что делать, если подрядчик настаивает на root, потому что "иначе неудобно работать"?

Уточните конкретно, какая команда или операция требует root, и выдайте sudo-права именно на неё, а не на всё сразу. В подавляющем большинстве задач — от настройки cron до перезапуска сервиса — точечный sudo закрывает потребность полностью.

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

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

Что если подрядчик работал через общий VPN компании, а не напрямую по SSH?

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

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

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

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

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

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