Здравствуйте!
На самом деле это одна из моих излюбленнейших "фишек" 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 с клиента.
Егор