В работе команды системных администраторов наступает момент, когда поддерживаемых серверов становится слишком много. А может быть еще и людей много, ну и опять же безопасность: если что-то пошло не так, нужно отовсюду ключи удалять.
У нас 300 клиентов. Кому-то это «всего», а для нас — это почти 2000 серверов на обслуживании. Чтобы хранить, обновлять и управлять базой из 2000 паролей для 60 сотрудников, управлять доступом к ней и не объяснять каждый раз клиенту, что пароли к его серверам будут одновременно знать 60 человек, мы сделали сервер аутентификации и назвали его Isolate. Под катом описание функций и ссылка на Github — мы выложили его в Open Source.
У нас есть отдельные серверы авторизации, через которые сотрудники попадают на конкретный поддерживаемый сервер. Мы сами давно и успешно пользуемся этой разработкой, а теперь решили дать ей имя и поделиться с сообществом.
Итак, Isolate — набор утилит auth сервера и ansible-playbook для быстрого его разворачивания. Он позволяет нам авторизовываться по аппаратному ключу (безопасность превыше всего!) и удобно управлять огромным количеством проектов/серверов. При этом:
- сотрудники не знают root пароль (опять же безопасность);
- при нештатных ситуациях аппаратный ключ сотрудника деактивируется на auth сервере, и он теряет доступ к клиентским серверам (к счастью, у нас таких ситуаций не было);
- все SSH-сессии записываются — можно считать время, проведенное на серверах.
Принимая сервер на поддержку, мы создаем на нем sudo-пользователя и прописываем ключ auth серверов. Дальше сотрудник авторизуется на auth сервере с использованием аппаратного ключа (мы используем yubikey), командой s (search) находит нужный сервер (по имени проекта, сервера, сайта и т.п.) и командой g (go) подключается к нему по SSH.
Основные моменты Isolate:
- у пользователей нет доступа к приватному ключу;
- все исходящие SSH-сессии логируются;
- используются только системные средства управления доступом (поддержка SELinux в ближайшем будущем);
- вход на Isolate выполняется по одноразовому паролю (2FA, OTP); можно использовать либо аппаратные ключи, либо всеми любимый Google Authentificator;
- менеджер конфигураций SSH с возможностью соединения через SSH прокси-сервер, поддержка серверов в VPN через внешний гейт;
- устанавливается через Ansible, но требует вмешательства в системные файлы (в ручном режиме);
- поддерживаются CentOS 7, Ubuntu 16.04, Debian 9.
Как это выглядит
Пример списка серверов:
[~]$ s .
myproject
------
10001 | 11.22.22.22 | aws-main-prod
10002 | 11.33.33.33 | aws-dev
10003 | 11.44.44.44 | vs-ci
------
Total: 3
[~]$
точка
s .
в данном случае — как универсальный патерн для поиска всех серверов.Пример входа на сервер с кастомным портом и SSH-proxy:
[~]$ g myproject aws-dev
Warning: Permanently added 3.3.3.100 (RSA) to the list of known hosts.
Warning: Permanently added 10.10.10.12 (RSA) to the list of known hosts.
[root@dev ~]$
Пример входа на произвольный сервер (без конфига в ISOLATE) c произвольными параметрами:
[isolate ~]$ g 45.32.44.87 --user support --port 2232 --nosudo
Warning: Permanently added 45.32.44.87 (RSA) to the list of known hosts.
Принцип работы
Установка достаточно подробно описана в README на Github, тут же поговорим о принципах работы.
Сам доступ разграничивается системными пользователями ОС. Как прослойка для доступа используется sudo + ssh.py обертка, цель которой — не допустить попадания за sudo опасных конструкций; ssh.py верифицирует аргументы и запускает SSH-клиент, на этом его обязанности заканчиваются.
Например:
$ sudo -l
(auth) NOPASSWD: /opt/auth/wrappers/ssh.py
$ sudo /opt/auth/wrappers/ssh.py -h
usage: ssh-wrapper [-h] [--user USER] [--port PORT] [--nosudo]
[--config CONFIG] [--debug] [--proxy-host PROXY_HOST]
[--proxy-user PROXY_USER] [--proxy-port PROXY_PORT]
[--proxy-id PROXY_ID]
hostname
positional arguments:
hostname server address (allowed FQDN,[a-z-],ip6,ip4)
optional arguments:
-h, --help show this help message and exit
--user USER set target username
--port PORT set target port
--nosudo run connection without sudo terminating command
--debug
--proxy-host PROXY_HOST
--proxy-user PROXY_USER
--proxy-port PROXY_PORT
--proxy-id PROXY_ID just for pretty logs
------
Этот скрипт также отвечает за логирование — он формирует имена лог файлов и их расположение, определяет имя пользователя, сделавшего sudo, создает каталоги для лог файлов. Рядом с каждым логом есть *.meta файл, содержащий объект текущего соединения в JSON.
Скрипт helper.py включает в себя все основные функции, изоляция с ssh.py позволит реализовать даже сложную логику без опасения ошибки с определением прав пользователя или какой либо еще небезопасной функцией.
В скрипт завернуты функции, используемые в shared/bootstrap.sh.
Например, поиск сервера:
s () {
if [[ $# -eq 0 ]] ; then
echo -e "\\n Usage: s <query> \\n";
return
elif [[ $# -gt 0 ]] ; then
"${ISOLATE_HELPER}" search "${@}";
fi
}
Работать с прокси можно без установки дополнительных пакетов. Достаточно SSH-сервера и установленного на нем nc/netcat. Также можно использовать функцию проброса порта в современных SSHD/SSH, но эта методика не рекомендуется, так как еще довольно много устаревших SSHD, которые не поддерживают эту функцию.
При попытке соединиться функцией/alias g, также, вызывается helper.py, который проверяет аргументы, классифицирует адрес/IP/FQDN/project и запускает ssh.py с нужными аргументами. При попытке входа по IP/FQDN без указания project/group будет использован default конфиг для SSH.
Все настройки для сервера доступны только при точном указании, например:
$ g rogairoga nyc-prod-1
Или, если сервер находится за корпоративным прокси после имени проекта, можно указать любой адрес FQDN/IP.
$ g rogairoga 192.168.1.1
все обычные для g дополнительные аргументы также доступны:
$ g rogairoga 192.168.22.22 --port 23 --user support --nosudo
также есть возможность входа по ID сервера.
$ g 12345
Вместо заключения
Исходный код Isolate выложен на Github. Надеемся, что наше решение поможет многим DevOps-командам структурировать и упростить работу с серверами. Ждем комментариев, пожеланий и, конечно же, пул реквестов! Предложить идеи или задать вопросы можно в Телеграм-чате.
Наши дальнейшие планы:
- разграничение прав доступа (пользователь-проект);
- хелпер для трансфера файлов через auth сервер с/на конкретную машину;
- интеграция с Zabbix (Tech Preview уже есть!).
И следом хотим заопенсорсить наш Телеграм-клиент — про неё можно почитать тут.
Комментарии (23)
XakRU
27.07.2017 19:07+1при нештатных ситуациях аппаратный ключ сотрудника деактивируется на auth сервере, и он теряет доступ к клиентским серверам (к счастью, у нас таких ситуаций не было);
Как обстоят дела при потери сетевой связанности с сервером авторизации?
Кто после внештатных ситуаций восстанавливает работу сервера?
Что вы имеете в виду под внештатными ситуациями?
все SSH-сессии записываются — можно считать время, проведенное на серверах.
Централизованный сервер SYSLOG для сбора логов — решает эту задачу на отлично. Можно расширить функционал средствами audit, snoopy, grsec.
Чем плох вариант установки ключей пользователя на удаленной системе если управление уже осуществляется средствами ansible?
Ведь также средствами ansible можно управлять пользователями и их ключами.
Зачем знать рутовый пароль на сервере? SUDO — отметает необходимость знать рутовый пароль.
Закрытые ключи пользователей необходимо шифровать на локальных
Централизованная система аутентификации для linux не нова, Identity Management например.
Выпускать это в интернет — сомнительное предприятие, разве что в сегменте изолированной сети.Hile
27.07.2017 19:12Мы не написали сервис аутентификации, это просто гейт с функциями логирования и OTP паролями,
>Как обстоят дела при потери сетевой связанности с сервером авторизации?
Как обычно теряешь доступ к серверу ))
>что после внештатных ситуаций восстанавливает работу сервера?
Мы не храним у себя никаких состояний (кроме мониторинга), вход к клиенту по ключу. Никаких пакетов клиенту ставить нет необходимости.
>Что вы имеете в виду под внештатными ситуациями?
Потеря лаптопа с приватным ключом или его кража.XakRU
27.07.2017 19:18Т.е. Вы написали гейт для себя, но слабо описано его применение и области где бы это было удобно, почему удобно, с чем сравнивать, какие альтернативы?
Ну не страшно если нуоутбук украли, закрытый ключ ведь зашифрован. Или у Вас нет практики шифрования закрытого ключа?Hile
27.07.2017 19:30Представьте себя, на месте клиента, у вас на сервере, без контроля, без достоверного лога, с разных ip приходят админы с рутовым доступом…
Так же важно, в нашем случае, поддерживать некий журнал действий на случай разрешения сложных ситуаций, ошибки со стороны админов бывают, мы не идеальны. Хорошо когда ошибку можно найти сразу или она сразу дала о себе знать, но когда это произошло на прошлой неделе и уже давно выветрилось из памяти, приходится грепать логи, хорошо когда они есть ))XakRU
27.07.2017 19:40Но вы ведь не предоставляете доступ клиенту к Вашему гейту? Логи находятся только у Вас на собственных серверах.
Журнал действий тогда честно было бы иметь и заказчику на своем сервере сислог.Hile
27.07.2017 19:56Ну это уже можно решить на месте, те частный случай :)
А в массовом применении иначе, к сожалению никак, ибо ОС разные у клиентов и нужно много времени и велик риск вызвать сбой или любой другой побочный эффект (использовал иное решение у прошлого работодателя )
Hile
27.07.2017 19:17> Централизованный сервер SYSLOG для сбора логов — решает эту задачу на отлично. Можно расширить функционал средствами audit, snoopy, grsec.
ну и вот это упустил,
Это требует вмешательства в ПО клиента, в нашем же случае, логи падают в файл на диске и по опыту, данная связка очень надежна и проста.XakRU
27.07.2017 19:19но таким же образом можно ssh завернуть в функцию для дублирования потока в файл на диске без гейта.
Hile
27.07.2017 19:21По сути это комплекс небольших решений, там если посмотрите так и сделано ) Суть в том, что остается контроль за действиями админа. Тк у него нет полного доступа к приватному ключу.
LuckyRaul
28.07.2017 00:21+1В чем отличие от готовых открытых решений? например sshkeybox? или vault?
Еще смотря видео и презентации думал увидеть какой-то продукт цельный, а тут оказался набор скриптов (рыбка на ножках очень в тему )Hile
28.07.2017 00:28Ну по сути это набор скриптов, часть нашего Flow если можно так выразится, решили поделится, тк вопрос у меня лично пару раз такой был, чтоб было удобно и безопасно, но в то же время просто, я постарался это собрать сам для своих коллег, тк прошлое решение меня не устраивало :)
Ну и отличия я просто не знаю, я увидел решение и просто собрал, тут из сложностей пожалуй только хранение информации о сервере и данных о прокси если необходим, при этом SUDO выполняет роль «крайнего» что нахожу очень удобным и надежным. Т.к за ним валидация тоже есть.
Hile
28.07.2017 00:31KeyBox is a web-based SSH console / irony
А это разве не минус ?))LuckyRaul
28.07.2017 00:41+1зато цельный продукт )
вот еще
https://github.com/aker-gateway/Aker
https://github.com/iamacarpet/ssh-bastion
другой подход на SSH CA
https://github.com/Netflix/bless
Вариантов реализации не так много. Либо CA сервер либо OTP прокси. Оба варианта кстати реализованны в Vault.Hile
28.07.2017 01:20У меня не было выбора) Не кастомное решение потребовало бы переучивать коллег ))
grossws
28.07.2017 01:26[~]$ g myproject aws-dev
Warning: Permanently added 3.3.3.100 (RSA) to the list of known hosts.
Warning: Permanently added 10.10.10.12 (RSA) to the list of known hosts.Очень насторожило. Ваш гейт доверяет всем серверам без вопросов и и считает, что MItM — это байки?
Hile
28.07.2017 11:35На этапе отладки решения, очень сложно следить еще и за этим, включить проверку не сложно, если дойдет до установки.
Тут это скорее для наглядности.
DuD
28.07.2017 13:56+1Смотрели ли рынок на предмет готовых решений? Та же FreeIPA к примеру, почему не подошла?
diafour
28.07.2017 14:45поддерживаются CentOS 7, Ubuntu 16.04, Debian 9.
Также можно использовать функцию проброса порта в современных SSHD/SSH, но эта методика не рекомендуется, так как еще довольно много устаревших SSHD, которые не поддерживают эту функцию.Непонятно. Можно подробнее про неподдерживаемый проброс порта?
Hile
28.07.2017 15:06на ssh серверах в старых версиях, не везде работает
$ ssh -o ProxyCommand=«ssh -W %h:%p firewall.example.org» server2.example.org
https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Proxies_and_Jump_Hosts
у нас более универсальный вариант с netcat/nc используется
apro
А можете пояснить в чём отличие от основанных на LDAP решениях, и почему приняли решение писать еще один сервис для аутентификации?
Hile
А все очень просто )
Это не сервис аутентификации(в каком то смысле), этим тут занимается ОС (sudo и pam). При желании можно использовать совместно с LDAP ничего сложного под капотом нет. А разворачивать LDAP на 2к серверов разных клиентов и поддерживать довольно сложная задача, на это просто нет времени ( как я понял основной вопрос в этом )
Велосипед к моему приходу был, переделывал его и облагораживал как умел в последствии.
Аналогов не искал, потому что все привыкли к одной схеме и шоткатам, переучить команду довольно сложно))
Так же, в нашей реализации (внутренняя разработка) были сохранены все legacy функции и аргументы, так, чтоб команда не чувствовала дискомфорта.
p.s. если в двух словах, это логгер, точка входа для инженера и менеджер конфигураций ssh
apro
Хм.., вообще-то с ldap авторизация тоже возможна через pam и sudo
А зачем? ldap серверов конечно может быть (и нужно для отказоустойчивости) больше
одного, но зачем каждому, на всех 2000 серверах могут быть только клиенты
и нужно залить только конфиг. Причем клиенты штатные pam_ldap я думаю в каждый дистрибутив входит.
Но в общем вы ответили на мой вопрос, спасибо.
Hile
Я просто не с той ноги начал)
на 2к серверов которые админили до нас, бывает довольно сложно интегрировать новые схемы аутентификации, а в случае проблем с сетью, мы не сможем войти к клиенту, для нас удобнее механизм публичных ключей ssh на отрезке бастион->сервер клиента — за счет своей простоты. плюс мы никак не удерживаем клиента своими конфигами, обычно достаточно удалить нашего пользователя и агента мониторинга.