
Привет! Меня зовут Амир Уразалин, я DevOps-инженер в KTS.
В аутсорсинговой модели мы одновременно ведем несколько крупных проектов, каждый со своей инфраструктурой, окружениями и требованиями безопасности. При этом команда инженеров общая, а доступ к виртуальным машинам должен управляться централизованно, прозрачно и безопасно.
По мере роста числа проектов и серверов управлять доступом становилось все сложнее, поэтому мы начали искать новое решение.
Оглавление
Где начали проявляться ограничения старой схемы
Изначально модель была классической: Ansible-плейбук на каждом проекте создавал пользователей и доставлял их публичные SSH-ключи на 100+ виртуальных машин. Это работало, но со временем стали заметны минусы такой схемы:
Нет связи с корпоративной учетной записью. Доступ к серверам определяется SSH-ключом, а не ролью пользователя или его актуальным статусом в компании.
Доступ приходится обновлять вручную на каждом проекте. При добавлении нового инженера нужно отдельно прогонять плейбуки на инфраструктуре каждого проекта.
Отзыв доступа занимает время. Чтобы убрать доступ, нужно прогнать playbook и убедиться, что он применился на всех хостах. Если какая-то машина была недоступна, то доступ может остаться, появляется угроза безопасности.
Сложно понять, кто подключался к серверу. При инциденте приходится искать информацию в логах на отдельных машинах.
Ansible отлично справляется с конфигурацией серверов, но доступ к инфраструктуре — это не только конфигурация, это политика и контроль. В какой-то момент стало очевидно: мы управляем ключами, но не управляем доступом.
А доступ к инфраструктуре все-таки должен определяться не наличием SSH-ключа на сервере, а ролью пользователя в корпоративной системе и актуальным статусом в компании. Стало понятно, что нужна другая модель доступа.
Доступ должен быть связан с корпоративной учетной записью. Инженер проходит аутентификацию через SSO, а права к серверам определяются его ролями или группами. Если человек меняет роль или уходит из компании, его доступ должен обновляться автоматически.
Важно, чтобы решение работало в продакшене без лицензионных ограничений. Плюс важно было иметь возможность управлять конфигурацией и списком серверов декларативно — чтобы не добавлять 100+ виртуальных машин вручную.
При этом единая точка входа не должна становиться single point of failure. Поэтому хотелось иметь возможность развернуть решение в Kubernetes и запустить несколько реплик для отказоустойчивости.
Разбираем, как мы внедрили клиентам Warpgate bastion с SSO, RBAC и IaC вместо набора jump-host и Ansible-плейбуков.
Что такое Warpgate
Warpgate — это опенсорсный сервис, который работает как прозрачный бастион-хост для доступа к внутренним и публичным ресурсам: SSH, HTTPS, базам данных (MySQL, PostgreSQL) и Kubernetes.
Warpgate принимает подключение пользователя, проверяет его аутентификацию и роли, после чего проксирует соединение напрямую к целевому ресурсу.
Важный момент: Warpgate работает без установки агентов на целевые серверы. Для внедрения не нужно разворачивать отдельные компоненты на каждой виртуальной машине.
Сервис поддерживает SSO и двухфакторную аутентификацию, записывает сессии и позволяет посмотреть историю подключений через встроенный веб-интерфейс. Фактически Warpgate становится единой точкой доступа к инфраструктуре, через которую проходят все подключения.
Чем Warpgate отличается от jump-хостов, VPN и Teleport
Обычно такие решения приходится дополнительно сравнивать и отдельно обосновывать выбор. В случае с Warpgate это оказалось проще: в README проекта на GitHub уже есть сравнительная таблица с отличиями от других подходов.
Warpgate | SSH jump host | VPN | Teleport |
✅ Точная привязка пользователей к конкретным сервисам | Обычно: полный доступ к сети за jump-хостом | Обычно: полный доступ к сети | ✅ Точная привязка пользователей к конкретным сервисам |
✅ Не нужен отдельный клиент | Требуется настройка jump-хоста | ✅ Не нужен отдельный клиент | Требуется отдельный клиент |
✅ 2FA из коробки | 🟡 2FA возможно через дополнительные PAM-плагины | 🟡 Зависит от провайдера | ✅ 2FA из коробки |
✅ SSO из коробки | 🟡 SSO возможно через дополнительные PAM-плагины | 🟡 Зависит от провайдера | Платно |
✅ Аудит на уровне команд | 🟡 Аудит только на уровне соединения на jump-хосте, без безопасного аудита на целевом хосте при наличии root-доступа | Безопасный аудит на целевом хосте невозможен при наличии root-доступа | ✅ Аудит на уровне команд |
✅ Полная запись сессий | Безопасная запись на целевом хосте невозможна при наличии root-доступа | Безопасная запись на целевом хосте невозможна при наличии root-доступа | ✅ Полная запись сессий |
✅ Неинтерактивные подключения | 🟡 Возможны, если клиент нативно поддерживает jump-хост | ✅ Неинтерактивные подключения | Для неинтерактивных подключений нужен SSH-wrapper или запуск туннеля |
✅ Self-hosted, данные хранятся у вас | ✅ Self-hosted, данные хранятся у вас | 🟡 Зависит от провайдера | SaaS |
Источник: официальное сравнение в README проекта Warpgate на GitHub, перевод мой.
Для нас здесь были важны простые вещи: SSO без лишних костылей, отсутствие лицензионных ограничений и возможность управлять доступами и конфигурацией через код. По этому набору требований Warpgate нам подошел лучше всего.
Архитектура решения
Чтобы было проще понять, как все это работало на практике, ниже я набросал упрощенную схему взаимодействия основных компонентов.

SSO через Keycloak
Аутентификацию в Warpgate мы настроили через Keycloak по OIDC. В Keycloak у нас заведены группы, которые соответствуют ролям или проектам. Например, группа /teams/devops/project-A означает, что пользователь должен получить доступ к инфраструктуре проекта project-A.
Дальше схема простая: человека добавляют в нужную группу в Keycloak, после чего он заходит в Warpgate через SSO. Warpgate получает группы пользователя из OIDC-токена, автоматически создает ему аккаунт и назначает роль по настроенному маппингу.
За счет этого доступ к проектам управляется через группы в Keycloak. Чтобы выдать доступ, достаточно добавить человека в нужную группу. Чтобы отозвать — убрать из нее.
Ниже показана часть конфигурации warpgate.yaml:
sso_providers: - name: keycloak label: "Login with Keycloak" auto_create_users: true provider: type: custom client_id: warpgate client_secret: $OIDC_CLIENT_SECRET issuer_url: $ISSUER_URL scopes: ["openid", "email"] role_mappings: '/teams/devops/warpgate-admin': 'warpgate:admin' '/teams/devops/project-A': 'project-A' '/teams/devops/project-B': 'project-B'
В этом примере группа /teams/devops/warpgate-admin маппится на админскую роль в Warpgate, а группа /teams/devops/project-A — на роль, которая дает доступ к ресурсам проекта project-A.
Доступ к инфраструктуре as-a-code
У Warpgate есть свой Terraform Provider, и мы активно его используем. Через него мы описываем не просто список серверов, а всю схему доступа: какие есть роли, к каким ресурсам они привязаны и через какой шлюз идет подключение.
Для нас это особенно важно, потому что проектов много. Если управлять ресурсами, ролями и доступами вручную через UI, то при росте числа проектов такая схема просто перестает масштабироваться. Особенно это заметно при подключении нового клиента: если в его инфраструктуре 100+ серверов, заводить их руками в интерфейсе долго, неудобно и просто рискованно — слишком легко ошибиться в адресах, ролях или привязках доступа.
Сама Terraform-структура у нас отражает простую идею. В корне описан центральный Warpgate. Дальше каждый клиентский проект вынесен в отдельную папку, чтобы все его ресурсы, роли и правила доступа лежали отдельно и не смешивались с другими.
Если инфраструктура проекта находится во внутреннем контуре и недоступна напрямую, внутри его папки появляется inner. В нем описан отдельный Warpgate, который играет роль шлюза и дает доступ к внутренним ресурсам клиента.

В итоге структура остается понятной: в корне находится центральная точка входа, а внутри проектов отдельно описан доступ до внутренних ресурсов клиента, например до виртуальных машин с внутренними IP.
Что Warpgate не делает
Важно понимать, что Warpgate не отменяет Ansible полностью. На целевых ВМ все равно нужен технический пользователь, под которым Warpgate будет подключаться к хостам.
Но разница в том, что этот пользователь один, и его не нужно создавать заново для каждого инженера. Вместо раскатки множества пользователей и SSH-ключей на все машины мы поддерживаем один технический доступ со стороны Warpgate, а права инженеров уже управляются централизованно через SSO и роли.
Это заметно проще масштабируется: когда в команде появляется новый инженер, не нужно раскатывать нового пользователя и новый SSH-ключ по всем проектам. Достаточно выдать ему нужную роль в SSO, а остальное уже отработает Warpgate.
Что изменилось на практике
Главный эффект от такого подхода — доступ инженеров к клиентской инфраструктуре больше не управляется через персональные SSH-ключи и локальных пользователей на серверах.
Онбординг упрощается, отзыв прав становится предсказуемее, а аудит и разбор инцидентов занимают заметно меньше времени. Заодно мы снизили риск того, что на стороне клиента останутся неактуальные доступы после ухода сотрудника или его перевода на другой проект.
В итоге схема доступа становится проще в сопровождении и лучше масштабируется на несколько клиентских проектов.
Если вы тоже используете Warpgate или похожие решения, делитесь опытом в комментариях, будет интересно сравнить подходы!
А если интересно почитать еще о том, как мы работаем с инфраструктурой, рекомендую статьи моих коллег:
