- Система управления конфигурацией — Chef, Puppet, Ansible, Salt
- Active Directory + sssd
- Разнообразные извращения в виде скриптов и ручного редактирования файлов
На мой субъективный взгляд, оптимальным вариантом централизованного управления является все-таки связка Active Directory + sssd. Преимущества данного подхода вот в чем:
- Действительно Единый централизованный каталог пользователей.
- Раздача прав sudo сводится к добавлению пользователя в определенную группу безопасности.
- В случае различных Linux-систем возникает необходимость вводить дополнительные проверки на определение ОС при использовании систем конфигурации.
Сегодняшняя сюита будет посвящена именно связке Active Directory + sssd для управления правами sudo и хранением ssh ключей в едином репозитории.
Итак, зал застыл в напряженном молчании, дирижер поднял палочку, оркестр приготовился.
Поехали.
Дано:
- Домен Active Directory testopf.local на Windows Server 2012 R2.
- Linux хост под управлением Centos 7
- Настроенная авторизация с использованием sssd
Оба решения вносят изменения в схему Active Directory, поэтому проверяем все на тестовом окружении и только потом вносим изменения в рабочую инфраструктуру. Хочу заметить — все изменения точечные и, по сути, добавляют лишь необходимые атрибуты и классы.
Действие 1: управление sudo ролями через Active Directory.
Для расширения схемы Active Directory необходимо скачать последний релиз sudo — 1.8.27 на сегодняшний день. Распаковываем, копируем файл schema.ActiveDirectory из каталога ./doc на контроллер домена. Из командной строки с правами администратора из директории, куда скопировали файл, запускаем:
ldifde -i -f schema.ActiveDirectory -c dc=X dc=testopf,dc=local
(Не забываем подставлять свои значения)
Открываем adsiedit.msc и подключаемся к контексту по умолчанию:
В корне домена создаем подразделение sudoers. (Буржуины упорно утверждают, что именно в этом подразделении демон sssd производит поиск на предмет sudoRole объектов. Однако, после включения детального дебага и изучения логов, было выявлено, что поиск производится по всему дереву каталога.)
Создаем в подразделении первый объект, принадлежащий классу sudoRole. Имя может быть выбрано абсолютно произвольно, так как служит исключительно для удобной идентификации.
Среди возможных доступных атрибутов из расширения схемы основными являются следующие:
- sudoCommand — определяет, какие команды разрешены к выполнению на хосте.
- sudoHost — определяет для каких хостов применяется данная роль. Может быть задано как ALL, так и для отдельного хоста по имени. Также возможно использование маски.
- sudoUser — указываем, каким пользователям разрешено выполнение sudo.
В случае указания группы безопасности, в начале имени добавляем знак “%”. Если в имени группы присутствуют пробелы, беспокоиться не о чем. Судя по логам, задачу экранирования пробелов берет на себя механизм sssd.
рис 1. Объекты sudoRole в подразделении sudoers в корне каталога
рис 2. Членство в группах безопасности, указанных в sudoRole-объектах.
Следующая настройка производится на стороне Linux.
В файле /etc/nsswitch.conf добавляем в конец файла строку:
sudoers: files sss
В файле /etc/sssd/sssd.conf в секции [sssd] в сервисы добавляем sudo
cat /etc/sssd/sssd.conf | grep services
services = nss, pam, sudo
После всех операций нужно очистить кэш sssd демона. Автоматическое обновление производится раз в 6 часов, но зачем нам столько ждать, когда мы хотим уже сейчас.
sss_cache -E
Частенько случается так, что очистка кэша не помогает. Тогда останавливаем сервис, чистим базу, стартуем сервис.
service sssd stop
rm -rf /var/lib/sss/db/*
service sssd start
Подключаемся под первым пользователем и проверяем, что ему доступно из-под sudo:
su user1
[user1@testsshad log]$ id
uid=1109801141(user1) gid=1109800513(domain users) groups=1109800513(domain users),1109801132(admins_)
[user1@testsshad log]$ sudo -l
[sudo] password for user1:
Matching Defaults entries for user1 on testsshad:
!visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin,
env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS",
env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE",
env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES",
env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE",
env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY",
secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin
User user1 may run the following commands on testsshad:
(root) /usr/bin/ls, /usr/bin/cat
То же самое проделываем со вторым нашим пользователем:
su user2
[user2@testsshad log]$ id
uid=1109801142(user2) gid=1109800513(domain users) groups=1109800513(domain users),1109801138(sudo_root)
[user2@testsshad log]$ sudo -l
Matching Defaults entries for user2 on testsshad:
!visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin,
env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS",
env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE",
env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES",
env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE",
env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY",
secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin
User user2 may run the following commands on testsshad:
(root) ALL
Подобный подход позволяет централизованно определять роли sudo для различных групп пользователей.
Хранение и использование ssh ключей в Active Directory
При небольшом расширении схемы есть возможность хранить ключи ssh в атрибутах пользователя Active Directory и использовать их при авторизации на Linux хостах.
Должна быть настроена авторизация через sssd.
Добавляем нужный атрибут при помощи PowerShell скрипта.
$Prefix=«1.2.840.113556.1.8000.2554»
$GUID=[System.Guid]::NewGuid().ToString()
$Parts=@()
$Parts+=[UInt64]::Parse($guid.SubString(0,4),«AllowHexSpecifier»)
$Parts+=[UInt64]::Parse($guid.SubString(4,4),«AllowHexSpecifier»)
$Parts+=[UInt64]::Parse($guid.SubString(9,4),«AllowHexSpecifier»)
$Parts+=[UInt64]::Parse($guid.SubString(14,4),«AllowHexSpecifier»)
$Parts+=[UInt64]::Parse($guid.SubString(19,4),«AllowHexSpecifier»)
$Parts+=[UInt64]::Parse($guid.SubString(24,6),«AllowHexSpecifier»)
$Parts+=[UInt64]::Parse($guid.SubString(30,6),«AllowHexSpecifier»)
$oid=[String]::Format("{0}.{1}.{2}.{3}.{4}.{5}.{6}.{7}",$prefix,$Parts[0],
$Parts[1],$Parts[2],$Parts[3],$Parts[4],$Parts[5],$Parts[6])
$oid
}
$schemaPath = (Get-ADRootDSE).schemaNamingContext
$oid = New-AttributeID
$attributes = @{
lDAPDisplayName = 'sshPublicKey';
attributeId = $oid;
oMSyntax = 22;
attributeSyntax = «2.5.5.5»;
isSingleValued = $true;
adminDescription = 'User Public key for SSH login';
}
New-ADObject -Name sshPublicKey -Type attributeSchema -Path $schemapath -OtherAttributes $attributes
$userSchema = get-adobject -SearchBase $schemapath -Filter 'name -eq «user»'
$userSchema | Set-ADObject -Add @{mayContain = 'sshPublicKey'}
После добавления атрибута нужно перезапустить службу Active Directory Domain Services.
Переходим к пользователям Active Directory. Любым удобным для Вас способом генерируем пару ключей для ssh подключения.
Запускаем PuttyGen, нажимаем кнопочку «Generate» и судорожно елозим мышью в пределах пустой области.
По завершению процесса мы можем сохранить публичный и приватные ключи, залить публичный ключ в атрибут пользователя Active Directory и наслаждаться процессом. Однако публичный ключ необходимо использовать из окна "Public key for pasting into OpenSSH authorized_keys file:".
Добавляем ключ в атрибут пользователя.
Вариант 1 — GUI:
Вариант 2 — PowerShell:
get-aduser user1 | set-aduser -add @{sshPublicKey = 'AAAAB...XAVnX9ZRJJ0p/Q=='}
Итак, мы имеем на текущий момент: пользователь с заполненным атрибутом sshPublicKey, настроенный клиент Putty для авторизации по ключам. Остается один небольшой момент, как же заставить демон sshd вытягивать нужный нам публичный ключ из атрибутов пользователя. С этим успешно справляется небольшой скрипт, найденный на просторах буржуйского интернета.
cat /usr/local/bin/fetchSSHKeysFromLDAP
#!/bin/sh
ldapsearch -h testmdt.testopf.local -xb "dc=testopf,dc=local" '(sAMAccountName='"${1%@*}"')' -D Administrator@testopf.local -w superSecretPassword 'sshPublicKey' | sed -n '/^ /{H;d};/sshPublicKey:/x;$g;s/\n *//g;s/sshPublicKey: //gp'
Выставляем на него права 0500 для root.
chmod 0500 /usr/local/bin/fetchSSHKeysFromLDAP
В данном пример для бинда к каталогу используется учетная запись администратора. В боевых условиях должна быть отдельная учетная запись с минимальным набором прав.
Меня лично очень смущал момент пароля в чистом виде в скрипте, несмотря на выставленные права.
Вариант решения:
- Сохраняю пароль в отдельный файл:
echo -n Supersecretpassword > /usr/local/etc/secretpass
- Выставляю права на файл 0500 для root
chmod 0500 /usr/local/etc/secretpass
- Меняю параметры запуска ldapsearch: параметр -w superSecretPassword меняю на -y /usr/local/etc/secretpass
Финальным аккордом в сегодняшней сюите редактируем sshd_config
cat /etc/ssh/sshd_config | egrep -v -E "#|^$" | grep -E "AuthorizedKeysCommand|PubkeyAuthe"
PubkeyAuthentication yes
AuthorizedKeysCommand /usr/local/bin/fetchSSHKeysFromLDAP
AuthorizedKeysCommandUser root
Как следствие, получаем следующую последовательность при настроенной авторизации по ключам в ssh клиенте:
- Пользователь подключается к серверу, указывая свой логин.
- Демон sshd через скрипт вытягивает значение публичного ключа из атрибута пользователя в Active Directory и проводит авторизацию по ключам.
- Демон sssd производит дальнейшую аутентификацию пользователя на основании принадлежности к группе. Внимание! Если таковая не сконфигурирована, то любой пользователь домена будет иметь доступ к хосту.
- При попытке sudo происходит поиск демоном sssd в каталоге Active Directory на предмет ролей. При наличии ролей проверяются атрибуты и членство пользователя в группе (если sudoRoles настроены на использовании групп пользователей)
Итог
Таким образом ключи хранятся в атрибутах пользователя Active Directory, разрешения sudo — аналогично, доступ к хостам Linux по доменным учетным записям осуществляется путем проверки принадлежности к группе Active Directory.
Финальный взмах дирижерской палочки — и зал замирает в благоговейной тишине.
Ресуры, использованные при написании:
Комментарии (15)
tgz
01.05.2019 07:10Одно плохо, в linux нет других способов повысить права кроме как через suid бит. Что не безопасно.
chemtech
01.05.2019 14:42dizaar Подскажите. Сейчас есть ограничение на длину имени Linux хоста при вводе в домен Active Directory в 16 символов. В существующем домене Active Directory с windows и Linux хостами можно ли как-нибудь обойти это ограничение?
dizaar Автор
01.05.2019 14:46Сам с таким столкнулся при первичной настройке sssd. Решается довольно просто — в секции [sssd] добавляется переменная ad_hostname. В нее нужно вписать сокращенное имя рабочей станции, которое можно посмотреть через klist -tke, либо в свойствах учетной записи рабочей станции в домене. Главное, знак доллара в конце не забыть.
Bessnov
01.05.2019 14:45Из плюсов вижу только хранение ключей в АДэ и то если есть доступ к контроллерам домена.
В большой сложившейся инфраструктуре расширять схему АДэ админы просто так не дадут, да и близко не подпустят, потому что чревато.
Из минусов:
— полуподпольный скрипт и хранение пароля на диске, т.е. предполагается что его регулярно менять нельзя, иначе всё развалится
— sssd это конечно последний новый писк моды, но вот нарвался на две неприятности которые никак не победить:
1. если в имени группы есть пробелы и символы "_" sssd делает лапки кверху при разборе имени группы.
2. на учётке пользователя порядка 400 групп (не задавайте вопросы «зачем»), id -a вытягивает список групп пользователя около 1,5 — 4 минут независимо от того что там закешировал sssd (winbind от samba3 делает так же)
Если не заморачиваться на хранение ключей и ролей в АДэ, то всё вполне решается подключением линукс хоста к домену в качестве рабочей станции через winbind samba4. Работает быстро, прозрачная авторизация через kerberos. Для ssh,sudo достатчно один раз прописать доменную группу.dizaar Автор
01.05.2019 14:51По поводу полуподпольного скрипта — ничего критичного в нем нет — обычный ldapsearch. Пробовал найти вариант бинда от имени рабочей станции, но — увы.
Пункт 1 — по последнему разбору пришлось долго читать километровые логи sssd — там все красиво и логично — и пробелы, и нижний слэш отлично разбираются. Кстати, если Вы внимательно посмотрите на скрины в статье — обе группы с нижним слэшем — и все работает тип-топ.
По поводу второго пункта — ничего не могу сказать, поскольку с такой ситуацией не сталкивался. А насчет «зачем» — всякое бывает) Надо, значит надо)
За winbind думал. Надо будет попробовать снова, не помню, почему данный вариант был отвергнут.
Насчет расширения схемы — согласен, дело опасное. Но данное расширение занимается исключительно добавлением новых атрибутов, а не изменением существующих атрибутов и класов. Опять же, повторюсь, тестовую среду никто не отменял.
Bessnov
01.05.2019 16:18по п.1 возможно у меня старая версия sssd
Например, на такую группу «р1 отдел разработки_5» он начинал ставить "_" вместо пробелов.
Увидев в конце "_5" он говорил «Ой, а тут _ уже есть» и, в итоге, представлял эту группу как несколько групп.
В общем, сколько ни есть историй про АДэ и линукс, у каждого свой уникальный случай. :)
vsantonov
01.05.2019 19:56Если есть немного денег можно купить продукт Centrify который интегрируется и в AD и в линукс и хорошо справляется с авторизацией и управлением sudo. Однако в реальной пользовательской среде это слегка утопично думать что вы сможете кому-то что-то запретить при их физическом доступе к машине. Элементарно винда не являющаяся частью домена просто ничего не может делать, а линукс вполне себе работоспособен. Как решение для серверной инфраструктуры еще есть смысл внедрять интеграцию с AD, для рабочих станций сомнительно.
kupch
03.05.2019 17:01+1Очень рекомендую pbis-open, делает аналогичные штуки, но работает чуть стабильнее чем sssd.
Самое интересное, что решение кроссплатформенное и на яблочных машинах работает идентично.
Ссылка на продукт:
github.com/BeyondTrust/pbis-open/wiki
ZaitsXL
Расскажите зачем использовать Active Directory в инфраструктуре с Линуксами? Все равно ведь большая часть функционала AD недоступна на Линуксах. Есть же нативные решения типа FreeIPA или 389ds.
flamencist
Есть же AD Samba 4, вполне себе нативное решение. Уже 2 года пользуемся и не жалуемся.
Tolmy
Даже достаточно одного OpenLDAP. Active Directory тут абсолютно избыточен.
dizaar Автор
Я прошу пардону, не уточнил в начале статьи. Общая структура такова:
Есть парк клиентских машин на Windows. Соответственно, имеется и инфраструктура Active Directory. Linux хосты — это сервера, выполняющие те или иные роли.
VitalKoshalew
Стандартная ситуация для среднего и крупного бизнеса: инфраструктура на Windows/AD, но есть виртуальные сервера с Linux. В такой ситуации AD-аутентификация для администрирования Linux-серверов — насущная необходимость. Наконец-то, не прошло и двух десятков лет, как это стало относительно легко сделать, благодаря sssd.
Dr_Wut
В целом уже ответили, но добавлю свои 5 копеек. 100-150 виндовых серверов и 15-20 линуксовых. Городить freeipa — вот это точно будет оверхедрм, а вот ренение автора прям огонь! Жаль что мне это уже не актуально, а то точно бы внедрил =)