Форум проекта Pro-LDAP.ru
Интеграция => Другие сервисы => Тема начата: marawu от 07 Октябрь 2016, 08:04:07
-
Доброго дня. Есть задача, настроить аутентификацию SSH по ключам из LDAP. Я нашел несколько статей как это сделать, но у всех разные механизмы. Хотя все они сходятся в том, что нужно добавить 2 новых атрибута на сервер. Вот тут у меня возникает первый вопрос, эти 2 атрибута лучше добавить отдельной схемой или добавить в какую-нибудь существующую? Так у меня вопрос к более опытным специалистам, если они настраивали такой механизм, как это сделать лучше?
-
Здравствуйте!
На самом деле это одна из моих излюбленнейших "фишек" LDAP-каталогов, наглядно демонстрирующая всю простоту и элегантность централизованного подхода хранения данных =) . До конца года я собирался написать статью по этому поводу, но раз уж у Вас созрел вопрос прямо сейчас, будем считать что это превью будущей статьи =) .
Нужно начать с того, что речь идёт об openssh и аутентификации по паре ключей. То есть сервер openssh знает некий набор "авторизованных" для данного пользователя открытых ключей, и если пользователь при попытке входа сумеет доказать, что он обладает одним из этих ключей и парным к нему закрытым ключом, то сервер будет считать аутентификацию пройденной и пустит пользователя без пароля.
Список "авторизованных" ключей пользователя лежит в его домашнем каталоге на сервере в файле ~/.ssh/authorized_keys. Если пользователь заходит по ssh с авторизацией по ключам на несколько серверов, то на каждом из них в файле authorized_keys должен присутствовать его открытый ключ. Со временем разработчики openssh поняли, что практически в каждой организации имеется централизованное хранилище данных пользователей в том или ином виде и что логичнее хранить общий открытый ключ для многих серверов именно в нём. И в openssh версии 6.2 появились директивы настройки, позволяющие черпать информацию об "авторизованных" ключах пользователя не только из файла authorized_keys, но и путём запуска сторонней программы, получающей на вход имя пользователя и выдающей на выход ключи этого пользователя. Как именно программа будет получать ключи этого пользователя оставляется на усмотрение разработчика этой программы.
Вот такой простейший подход, но одновременно и гениальный: храни ключи где хочешь в любой точке сети, отдай их по запросу серверу ssh и пользователь сможет на основании этого ключа пройти аутентификацию.
В данном случае LDAP-каталог -- однин из вариантов такого централизованного хранилища, причём вполне себе неплохой, с учётом того, что каталог есть практически в любой организации (тот же AD, к примеру). Поместил открытый ключ в один из свободных атрибутов, написал простейший скрипт поискового запроса LDAP, получающего содержимое этого атрибута из записи пользователя, имя которого передано на вход, и вывел извлечённый ключ на стандартный вывод, где его заберёт и оценит сервер openssh.
Повторюсь, атрибут для хранения ключа может быть любым текстовым (например, description или favoriteDrink), но общепринятой практикой является использование атрибута sshPublicKey из схемы данных проекта openssh-ldappubkey (решавшего задачу получения открытого ключа из каталога до появления openssh 6.2). Эту схему (во вложении) нужно добавить на сервер OpenLDAP, модифицировать запись пользователя, добавив ему вспомогательный объектный класс ldapPublicKey и его обязательный атрибут sshPublicKey, куда поместить открытый ключ пользователя из его пары ключей (обычно, содержимое файла ~/.ssh/id_rsa.pub). Примерный LDIF:
dn: uid=ivanov,ou=People,dc=mycompany,dc=ru
changetype: modify
add: objectClass
objectClass: ldapPublicKey
-
add: sshPublicKey
sshPublicKey:< file:///home/ivanov/.ssh/id_rsa.pub
Затем на сервере openssh в файле /etc/ssh/sshd_config раскомментировать или добавить строки:
AuthorizedKeysCommand /usr/bin/get_ldap_ssh_key.sh
AuthorizedKeysCommandUser nobody
В первой из них указывается имя скрипта извлечения ключа, во второй -- имя пользователя, с правами которого этот скрипт будет выполняться (в данном случае бесправный nobody).
Сам скрипт у меня простейший:
#!/bin/bash
# Параметры поиска в LDAP-каталоге
LDAP_URI="ldap://127.0.0.1:389"
BASE_DN="ou=People,dc=mycompany,dc=ru"
# Имя пользователя из первого аргумента вызова скрипта
SSH_USER=$1
# Получаем ключ
KEY=$(ldapsearch -x -LLL -o ldif-wrap=no -c -H "${LDAP_URI}" -b "${BASE_DN}" -S sshPublicKey "(&(uid=${SSH_USER})(sshPublicKey=*))" sshPublicKey | grep -v 'dn:' | perl -pe 's/sshPublicKey: //;')
# И выводим его
echo "${KEY}"
Остаётся дать права на исполнение данного скрипта, перезапустить openssh и пробовать зайти по ssh с клиента.
Егор
-
Первоначальная запись:
$ ldapsearch -x -LLL -H ldap://127.1:9000 -b dc=mycompany,dc=ru uid=ivanov
dn: uid=ivanov,ou=People,dc=mycompany,dc=ru
objectClass: inetOrgPerson
objectClass: posixAccount
uid: ivanov
cn: Ivan Ivanov
sn: Ivanov
userPassword:: aXZhbm92UGFzc3dvcmQ=
uidNumber: 1001
gidNumber: 1001
homeDirectory: /home/ivanov
loginShell: /bin/bash
LDIF-файл mod2.ldif:
dn: uid=ivanov,ou=People,dc=mycompany,dc=ru
changetype: modify
add: objectClass
objectClass: ldapPublicKey
-
add: sshPublicKey
sshPublicKey:< file:///home/ivanov/.ssh/id_rsa.pub
Применяем:
$ ldapmodify -x -D 'cn=manager,dc=mycompany,dc=ru' -w xxxxxxxxx -H ldap://127.1:9000 -f ./mod2.ldif
modifying entry "uid=ivanov,ou=People,dc=mycompany,dc=ru"
Что вышло:
$ ldapsearch -x -LLL -H ldap://127.1:9000 -b dc=mycompany,dc=ru uid=ivanov
dn: uid=ivanov,ou=People,dc=mycompany,dc=ru
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: ldapPublicKey
uid: ivanov
cn: Ivan Ivanov
sn: Ivanov
userPassword:: aXZhbm92UGFzc3dvcmQ=
uidNumber: 1001
gidNumber: 1001
homeDirectory: /home/ivanov
loginShell: /bin/bash
sshPublicKey:: c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCQVFDNVJvOVFLbWJ
IOXlOTExCMVBmbEkxbHN3Y21nSm1zaFFFTVlMWElYbytzdjhCeStqTFRKaFlIVEMydVBrNHZ0RHRw
R3JhYlgzcFlRK2NjbWRrMWxrRktXRUwxQzljdnlkNzYxcGE0Y3FKREJPUjl1MnQyUG9tSW0zTDJmR
kwrWWhuNldvZVZ6aW81OHVUc2p1TmFmc3E5bS9Eazc2enB3SjNUT1JKTzlIVmdZQUFYR2tqbENnUU
tnN1duMk9sOHQwNjdtS1BobEpwYWJiWEJkR0Yya0cvVDNmZXQ0N2V2ejExdGpVeC9VTlVQMjljSll
yZ3haL2tYZ08yZXViRzRNc2hMelZRUHk2NWpuZkE1TW9EL0JhZmdWQ0o2cjdqSitzcDV4R0IwcEk1
clpXNXA3Qkc3Uklhc0JOT3Q4K0hma2Rhc0ZpTHBwYkxaVU1seXR0NVB6Q2ggZWdvckBMZW5vdm8tW
W9nYS0yLTEzCg==
Файл с открытым ключом находится там, где Вы его указываете в URL file:// ? Вместо URL можно попробовать просто вставить текст открытого ключа из файла. Да, ещё, возможно, в записи нет атрибута uid, обязательного для класса ldapPublicKey, тогда его тоже нужно добавить в том же LDIF.
Егор