Как оформить доступ сотрудников к продакшену
Команда выросла с трёх человек до пятнадцати, а доступ к продакшену всё ещё выдаётся так же, как в первый месяц — общий root-пароль в чате или один SSH-ключ, который скопировали всем при найме. Работает, пока не увольняется человек, у которого этот ключ был, или пока кто-то не удаляет продакшн-таблицу, потому что зашёл туда «просто посмотреть логи» с правами администратора. Ниже — рабочая методика доступа для штатных сотрудников: как разграничить права по ролям, какими техническими средствами это делается и как закрыть доступ в день увольнения, а не через полгода.
Содержание
- Принцип наименьших привилегий на практике
- Ролевая матрица: кому что нужно на самом деле
- Именные аккаунты и группы Linux вместо общего логина
- Bastion-хост: одна точка входа вместо прямого SSH на продакшн
- Read-only доступ для финансов и аналитики без доступа к инфраструктуре
- Оффбординг: чек-лист отзыва доступа в день увольнения
- Учёт доступов без сложных систем — для маленькой команды
Принцип наименьших привилегий на практике
Принцип наименьших привилегий (principle of least privilege) звучит просто: у каждого сотрудника должен быть доступ ровно к тому, что нужно для его задач, и ни битом больше. На практике его почти всегда нарушают в одну сторону — выдают доступ «с запасом», потому что так проще закрыть вопрос сейчас. Через год у половины команды есть root на продакшн-сервер, хотя реально им пользуются два человека.
Правильная последовательность обратная: сначала описываете роль и задачи, потом — минимальный набор прав под эти задачи, и только потом заводите аккаунт с этим набором. Если через месяц прав не хватает — их добавляют точечно, а не выдают «на всякий случай» заранее. Это дороже в моменте выдачи доступа, но многократно дешевле, когда нужно разобраться, кто мог удалить файл или почему в базе изменились данные.
Ключевой вывод: доступ привязывается не к человеку и не к должности вообще, а к конкретной роли и системе. Разработчик Иван с фронтенда и разработчица Мария с биллинга могут иметь разный набор прав, даже если оба называются «разработчик», — потому что им нужны разные части инфраструктуры.
Ролевая матрица: кому что нужно на самом деле
Прежде чем что-то настраивать технически, полезно свести роли и права в таблицу — она же потом становится основой для аудита.
| Роль | Продакшн-серверы | Продакшн-БД | Staging | Логи приложения | Особенности |
|---|---|---|---|---|---|
| Разработчик | нет | нет | да, полный | да, чтение | доступ к БД — через staging-копию или анонимизированный дамп |
| DevOps/SRE | да, полный | да, полный | да | да | все действия логируются и хранятся отдельно от исполнителя |
| Тимлид/техлид | да, ограниченный (свой сервис) | да, чтение | да | да | может эскалировать до DevOps-доступа временно, с фиксацией причины |
| Финансы/аналитика | нет | нет (только read-only представления) | нет | нет | доступ к данным, не к инфраструктуре |
| Саппорт | нет | нет (панель поддержки) | нет | да, чтение по своему продукту | доступ через внутренний тул, не напрямую |
Для разработчиков ключевое ограничение — никакого прямого доступа к продакшн-базе данных. Это не недоверие к людям, а снижение количества точек, откуда может произойти случайная порча данных: чем меньше человек умеет выполнять DELETE FROM на боевой таблице, тем меньше шанс, что кто-то сделает это по ошибке в пятницу вечером. Если разработчику нужны реальные данные для отладки — заводится анонимизированный дамп на staging или доступ через read-реплику с отдельным ограниченным пользователем БД.
DevOps/SRE — противоположный случай: этим людям физически нужен широкий доступ к инфраструктуре, включая продакшн, потому что это их работа. Компенсация за широкие права — обязательное и неотключаемое логирование каждого действия. Широкий доступ без логирования — то же самое, что общий root-пароль, просто на одного человека вместо всех.
Финансовый и аналитический персонал — отдельная категория, которую часто решают неправильно: заводят человеку доступ к серверу «чтобы он сам выгрузил данные», хотя ему нужны не серверы, а конкретные цифры. Правильное решение — подготовленные read-only представления данных (материализованные вьюхи, отдельная аналитическая БД, дашборд), а не доступ к инфраструктуре вообще.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверИменные аккаунты и группы Linux вместо общего логина
Первое правило, без которого вся остальная схема не работает: у каждого сотрудника — свой именной аккаунт. Не admin, не deploy, не общий root на всех — а ivan.petrov, maria.sidorova, каждый со своим паролем/ключом. Без этого невозможен аудит: в логах будет просто «admin что-то сделал», а кто именно — придётся вспоминать по памяти или спрашивать в чате.
Создание пользователя и распределение по ролевым группам:
# создаём группы под роли
groupadd devs
groupadd devops
groupadd finance-readonly
# заводим именной аккаунт разработчика
useradd -m -s /bin/bash -G devs ivan.petrov
passwd -l ivan.petrov # блокируем вход по паролю
mkdir -p /home/ivan.petrov/.ssh
cp /tmp/ivan_id_ed25519.pub /home/ivan.petrov/.ssh/authorized_keys
chown -R ivan.petrov:ivan.petrov /home/ivan.petrov/.ssh
chmod 700 /home/ivan.petrov/.ssh
chmod 600 /home/ivan.petrov/.ssh/authorized_keys
Дальше — ограниченный sudo вместо полного root. В /etc/sudoers.d/ заводится отдельный файл на каждую роль (не правьте общий /etc/sudoers напрямую — используйте visudo -f):
# /etc/sudoers.d/devs-app-restart
%devs ALL=(root) NOPASSWD: /usr/bin/systemctl restart myapp
%devs ALL=(root) NOPASSWD: /usr/bin/systemctl status myapp
%devs ALL=(root) NOPASSWD: /usr/bin/journalctl -u myapp --since "1 hour ago"
Это даёт разработчику возможность перезапустить свой сервис и посмотреть логи, но не даёт прав на что-либо ещё — ни на файлы других сервисов, ни на сетевые настройки, ни тем более на базу данных. Для DevOps/SRE группа шире, но всё равно перечисляется явно, а не через ALL=(ALL) ALL:
# /etc/sudoers.d/devops-full
%devops ALL=(ALL) ALL
Defaults:%devops log_output
Defaults:%devops logfile=/var/log/sudo-devops.log
Директива log_output (модуль sudoers_io в современном sudo) пишет не только факт запуска команды, но и весь вывод сессии — это и есть базовое логирование действий DevOps, о котором говорилось выше. Логи стоит сразу форвардить на отдельный сервер логирования, чтобы человек с root-доступом физически не мог их подчистить на том же сервере, где работал.
Bastion-хост: одна точка входа вместо прямого SSH на продакшн
Второй технический слой — центральная точка входа. Вместо того чтобы у каждого продакшн-сервера был открыт 22-й порт наружу, все SSH-подключения идут через один bastion-хост (он же jump-host), а с него — дальше во внутреннюю сеть. Это даёт три вещи сразу: единую точку логирования всех подключений, возможность мгновенно отозвать доступ одному человеку без пересборки всей инфраструктуры, и меньшую площадь атаки — внутренние серверы просто не видны из интернета.
На bastion-хосте у каждого сотрудника — свой аккаунт и свой ключ, как описано выше. На стороне клиента доступ настраивается через ~/.ssh/config, чтобы не превращать каждое подключение в две команды:
Host bastion
HostName bastion.example.com
User ivan.petrov
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
Host prod-app-01
HostName 10.20.0.11
User ivan.petrov
ProxyJump bastion
IdentityFile ~/.ssh/id_ed25519_work
Дальше — ssh prod-app-01, и SSH сам прогоняет соединение через bastion прозрачно. На самом bastion-хосте полезно явно ограничить, кто вообще может через него проходить дальше, и включить подробное логирование:
# /etc/ssh/sshd_config на bastion
AllowUsers ivan.petrov maria.sidorova devops-*
LogLevel VERBOSE
PermitTunnel no
X11Forwarding no
AllowTcpForwarding local
LogLevel VERBOSE добавляет в логи отпечаток ключа, которым подключился пользователь, — это позволяет ответить на вопрос «кто заходил вчера в 23:40», не полагаясь на честность записи в общей таблице доступов. Если нужна ещё и запись самих сессий (что именно вводил человек в терминале), на bastion можно поставить auditd с правилами на execve, либо использовать готовые инструменты session recording (Teleport, Boundary) — они не бесплатны по объёму внедрения, но снимают вопрос «а что именно он там делал» без ручного разбора логов.
Ключевая практическая ошибка — заводить один общий ключ для bastion «чтобы не возиться с каждым сотрудником». Это возвращает к тому же общему логину, только узким местом становится не продакшн-сервер, а bastion. Личный ключ на человека — обязательное условие, без него аудит теряет смысл: логи покажут вход, но не покажут, кто именно.
Read-only доступ для финансов и аналитики без доступа к инфраструктуре
Финансовому и аналитическому персоналу почти никогда не нужен сервер — им нужны цифры: выручка, конверсии, использование ресурсов по клиентам. Выдавать таким сотрудникам SSH-доступ или логин в панель управления сервером — это доступ, который не решает их задачу, но добавляет ещё одну точку, которую нужно защищать и отзывать.
Правильная схема — отдельная read-only роль в базе данных, у которой физически нет прав на запись и нет доступа к таблицам, не относящимся к её задаче:
-- отдельная роль только на чтение
CREATE ROLE analytics_ro WITH LOGIN PASSWORD 'сгенерированный-пароль';
GRANT CONNECT ON DATABASE prod TO analytics_ro;
GRANT USAGE ON SCHEMA analytics_views TO analytics_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA analytics_views TO analytics_ro;
-- явно закрываем всё остальное
REVOKE ALL ON SCHEMA public FROM analytics_ro;
Схема analytics_views — это отдельный набор представлений (view), подготовленных под задачи аналитики, а не прямой доступ к боевым таблицам приложения. Такой слой решает две проблемы разом: аналитик не может случайно нагрузить продакшн тяжёлым запросом без LIMIT, и структура боевых таблиц может меняться без необходимости предупреждать всех, кто строит отчёты — представления остаются стабильными.
Ещё лучше — если аналитика вообще не подключается к базе напрямую, а смотрит данные через BI-инструмент (Metabase, Redash, Superset), подключённый к read-реплике. В этом случае сотруднику выдаётся логин в само приложение, а не сетевой доступ к серверу базы данных вообще — область, которую можно скомпрометировать, ещё меньше.
Оффбординг: чек-лист отзыва доступа в день увольнения
Самая частая практическая проблема — не в том, что доступ выдают неправильно, а в том, что его забывают отозвать. Сотрудник уволился в понедельник, а его SSH-ключ на bastion-хосте, VPN-конфиг и логин в панели хостинга остаются рабочими ещё полгода, просто потому что об этом никто не вспомнил. Это не гипотетический риск — это типовая находка на любом аудите доступов в компании, которая растёт быстрее, чем успевает наводить порядок в процессах.
Решение — не «постараться не забыть», а чек-лист, который проходят в день увольнения или смены роли, без исключений:
- SSH-ключи: удалить публичный ключ из
authorized_keysна bastion-хосте и на всех серверах, куда он мог быть скопирован напрямую в обход bastion. - Linux-аккаунт: заблокировать или удалить учётку (
usermod -L ivan.petrovдля немедленной блокировки,userdel -r ivan.petrovпри полном увольнении), убить активные сессии (pkill -u ivan.petrov). - VPN: удалить peer из WireGuard (
wg set wg0 peer <публичный-ключ> remove) или отозвать сертификат в OpenVPN (easyrsa revoke ivan.petrovи пересборка CRL). - Панели управления: снять доступ в панели хостинга/облака (учётка в панели провайдера, панель мониторинга, панель CI/CD).
- Облачные сервисы: отозвать доступ в IAM (например
aws iam delete-login-profile, отвязка политик, удаление access key), выйти из организации на GitHub/GitLab, деактивировать в Google Workspace/Slack. - Базы данных:
REVOKE ALL PRIVILEGES ... FROM ivan_petrov; DROP ROLE ivan_petrov;— если роль привязана к личным правам, а не к общей сервисной учётке. - Общие секреты: если человек имел доступ к общему хранилищу паролей (Vault, 1Password, Bitwarden) — не только убрать его оттуда, но и оценить, какие пароли стоит сменить, если они не были персональными для каждого.
На практике проще всего держать этот список не в голове, а в виде реального чек-листа (таск в трекере, шаблон в вики), который открывается при увольнении и закрывается только после того, как каждый пункт отмечен. Это тот случай, где формальность буквально экономит деньги — забытый доступ бывшего сотрудника не создаёт проблем в 99% случаев, но именно в оставшемся 1% это дорого обходится.
Учёт доступов без сложных систем — для маленькой команды
Bastion-хост, роли в Linux и read-only представления в БД — это правильная цель, но если в команде пять человек, разворачивать Teleport или писать Terraform под IAM-роли часто избыточно на старте. Минимально работающий вариант, который лучше, чем вообще никакого учёта — простая таблица, которую ведёт один ответственный человек:
| Сотрудник | Роль | Системы с доступом | Дата выдачи | Дата отзыва |
|---|---|---|---|---|
| Иван Петров | Разработчик | staging SSH, GitHub repo | 2026-01-15 | — |
| Мария Сидорова | DevOps | bastion, prod SSH, AWS IAM | 2025-11-02 | — |
| Олег Смирнов | Аналитик | Metabase read-only | 2026-03-10 | — |
Такая таблица не заменяет техническую реализацию наименьших привилегий, но решает главную проблему на старте — у компании появляется единый список того, кто и к чему имеет доступ, который можно открыть и свериться с реальностью раз в квартал. Если инфраструктура арендована на внешнем сервере (VPS или выделенный сервер), тот же принцип работает и там: bastion можно поднять на отдельной небольшой машине, не смешивая точку входа с боевыми серверами приложения.
Похожая логика разбирается в статье про то, как раздать доступ команде без выдачи root — там больше деталей именно про sudo и группы для небольшой команды. Если нужен инструмент для быстрой раздачи VPN-доступа с индивидуальными ключами и мгновенным отзывом, без ручной возни с WireGuard-конфигами, стоит посмотреть на Outline Manager. А чтобы закрыть вопрос «кто и когда подключался» на уровне VPN отдельно от SSH-логов, пригодится схема из статьи про аудит доступов VPN.
Стоит отдельно отметить: вся эта методика написана про штатных сотрудников — тех, кто работает в компании постоянно и по мере роста команды получает новые роли. Со временными подрядчиками и фрилансерами логика доступа немного другая — там обычно короче срок жизни доступа и жёстче ограничение по объёму задачи с самого начала, а не расширение прав со временем; если нанимаете внешнего исполнителя под разовую задачу, будет полезна статья о том, как составить ТЗ на настройку сервера для фрилансера — там разбирается похожий вопрос, но с обратной стороны, до того как доступ вообще выдан.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
С чего начать, если сейчас у всех root и общий пароль?
Не пытайтесь переделать всё за один день. Сначала заведите именные аккаунты всем, кто сейчас пользуется общим доступом, параллельно со старым доступом. Убедитесь, что все перешли на личные ключи и всё работает. Только после этого отключайте общий пароль/ключ — иначе рискуете разом обрубить доступ всей команде посреди рабочего дня.
Нужен ли bastion-хост, если сервер всего один?
Если инфраструктура — это один сервер, отдельный bastion избыточен: важнее сами именные аккаунты, ограниченный sudo и логирование. Bastion становится оправданным, когда серверов несколько и нужна единая точка входа и аудита.
Как быть, если DevOps-инженер должен видеть вообще всё?
Широкий доступ — нормальная часть роли DevOps/SRE, проблема не в объёме прав, а в отсутствии логирования этого доступа. Компенсируйте широту прав обязательной записью сессий (sudo с log_output, аудит на bastion) и хранением логов отдельно от машины, на которой работал сотрудник.
Что делать с доступом, который выдали «временно» полгода назад и забыли?
Это типовая находка при первом аудите. Решение системное — не разовая чистка, а плановая ревизия доступов (раз в квартал сверка таблицы или ролей с реальным составом команды), а не полагаться на то, что кто-то вспомнит вручную.
Можно ли обойтись без sudoers-файлов, просто добавив нужных людей в группу sudo целиком?
Технически можно, но это снова полный root по факту — группа sudo/wheel без ограничений даёт те же права, что и общий root-пароль, только через личный логин. Смысл ограниченных sudoers.d-файлов именно в том, чтобы разрешить конкретные команды, а не всё подряд.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →