Аутентификация по ключу SSH с использованием LDAP

59

Короче говоря:

Хотел бы получить способ аутентификации по SSH-ключу через LDAP.

Проблема:

Мы используем LDAP (slapd) для служб каталогов, и недавно мы перешли на использование нашего собственного AMI для создания экземпляров. Причина, по которой бит AMI важен, состоит в том, что в идеале мы хотели бы иметь возможность войти в систему с помощью SSH с помощью аутентификации по ключу, как только экземпляр будет запущен, и не нужно ждать, пока наш несколько медленный инструмент управления конфигурацией запустит скрипт для добавления правильные ключи к экземпляру.

Идеальный сценарий заключается в том, что при добавлении пользователя в LDAP мы также добавляем его ключ, и он сразу же сможет войти в систему.

Аутентификация по ключу обязательна, потому что вход на основе пароля менее безопасен и утомителен.

Я прочитал этот вопрос, который предполагает, что есть патч для OpenSSH под названием OpenSSH-lpk, чтобы сделать это, но это больше не требуется с сервером OpenSSH> = 6.2

Добавлена ​​опция AuthorizedKeysCommand sshd_config (5) для поддержки выборки авторизованных ключей из команды в дополнение (или вместо) из файловой системы. Команда запускается под учетной записью, указанной параметром AuthorizedKeysCommandUser sshd_config (5)

Как я могу настроить OpenSSH и LDAP для реализации этого?

c4urself
источник

Ответы:

64

Обновите LDAP, чтобы включить схему OpenSSH-LPK

Сначала нам нужно обновить LDAP схемой, чтобы добавить sshPublicKeyатрибут для пользователей:

dn: cn=openssh-lpk,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: openssh-lpk
olcAttributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
    DESC 'MANDATORY: OpenSSH Public key'
    EQUALITY octetStringMatch
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
olcObjectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
    DESC 'MANDATORY: OpenSSH LPK objectclass'
    MAY ( sshPublicKey $ uid )
    )

Создайте скрипт, который запрашивает LDAP для открытого ключа пользователя:

Сценарий должен вывести открытые ключи для этого пользователя, например:

ldapsearch '(&(objectClass=posixAccount)(uid='"$1"'))' 'sshPublicKey' | sed -n '/^ /{H;d};/sshPublicKey:/x;$g;s/\n *//g;s/sshPublicKey: //gp'

Обновить, sshd_configчтобы указать на сценарий из предыдущего шага

  • AuthorizedKeysCommand /path/to/script
  • AuthorizedKeysCommandUser nobody

Бонус : обновление, sshd_configчтобы разрешить аутентификацию по паролю из внутренних сетей RFC1918, как показано в этом вопросе:

Разрешить аутентификацию по паролю только для SSH-сервера из внутренней сети

Полезные ссылки:

РЕДАКТИРОВАТЬ: Добавлен пользователь, nobodyкак предложено TRS-80

c4urself
источник
6
Это фантастика, хотя я бы предложил AuthorizedKeysCommandUser nobodyвместо root.
TRS-80,
Должно быть что-то иное в моем ldapsearch или sed, потому что передача вывода в имеющуюся там команду sed black magic не дает мне вывода, даже если моя простая команда ldapsearch возвращает данные. Я собираюсь написать скрипт для очистки вывода вместо использования sed.
Крис Л
1
Не обращайте внимания на мой предыдущий комментарий. Моя проблема была вызвана наличием завершающего символа новой строки в свойстве sshPublicKey, что, в свою очередь, заставляет ldapsearch кодировать base64 целиком. Я упростил команду sed tho:ldapsearch -u -LLL -o ldif-wrap=no '(&(objectClass=posixAccount)(uid='"$1"'))' 'sshPublicKey' | sed -n 's/^[ \t]*sshPublicKey:[ \t]*\(.*\)/\1/p'
Крис Л
1
@Chris действительно менее чёрная магия, но sed - это
однонаправленная хеширующая
1
На моей версии OpenSSH (5.3p1-122.el6) есть AuthorizedKeysCommandRunAsи нетAuthorizedKeysCommandUser
mveroone
5

Для тех, кто получает ошибку при запуске ldapsearch:

sed: 1: "/^ /{H;d};": extra characters at the end of d command

как я и делал (во FreeBSD), исправление состоит в том, чтобы изменить первую команду sed на:

/^ /{H;d;};

(добавляя точку с запятой после 'd').

Скотт
источник
4

Я просто хотел поделиться своим «методом», моя клиентская часть специфична для Debian / Ubuntu, но моя серверная сторона в основном такая же, как указано выше, но с немного большим «HowTo:»

Сервер:

Включить атрибут открытого ключа:

Кредит:

https://blog.shichao.io/2015/04/17/setup_openldap_server_with_openssh_lpk_on_ubuntu.html

cat << EOL >~/openssh-lpk.ldif
dn: cn=openssh-lpk,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: openssh-lpk
olcAttributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
  DESC 'MANDATORY: OpenSSH Public key'
  EQUALITY octetStringMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
olcObjectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
  DESC 'MANDATORY: OpenSSH LPK objectclass'
  MAY ( sshPublicKey $ uid )
  )
EOL

Теперь используйте это, чтобы добавить ldif:

ldapadd -Y EXTERNAL -H ldapi:/// -f ~/openssh-lpk.ldif

Добавление пользователя с открытым ключом SSH в phpLDAPadmin

Сначала создайте пользователя с помощью шаблона «Generic: User Account». Затем перейдите в раздел атрибутов «objectClass», нажмите «Добавить значение» и выберите атрибут «ldapPublicKey». После отправки вернитесь на страницу редактирования пользователя, нажмите «Добавить новый атрибут» в верхней части и выберите «sshPublicKey», вставьте открытый ключ в текстовую область и, наконец, нажмите «Обновить объект». "

Атрибут sshPublicKey не отображается - OpenLDAP PHPLDAP SSH Key Auth

Клиент Ubuntu:

apt-get -y install python-pip python-ldap
pip install ssh-ldap-pubkey
sh -c 'echo "AuthorizedKeysCommand /usr/local/bin/ssh-ldap-pubkey-wrapper\nAuthorizedKeysCommandUser nobody" >> /etc/ssh/sshd_config' && service ssh restart

Создать тестовые ключи:

ssh-keygen -t rsa
FreeSoftwareServers
источник
3

Это не полный ответ, а дополнение к ответу c4urself . Я бы добавил это как комментарий, но у меня нет достаточной репутации, чтобы комментировать, поэтому, пожалуйста, не понижайте голос!

Это скрипт, который я использую для AuthorizedKeysCommand(на основе версии c4urself). Он работает независимо от того, возвращено ли значение в кодировке base64 или нет. Это может быть особенно полезно, если вы хотите хранить несколько авторизованных ключей в LDAP - просто разделите ключи символами новой строки, подобно файлу авторизованных ключей.

#!/bin/bash
set -eou pipefail
IFS=$'\n\t'

result=$(ldapsearch '(&(objectClass=posixAccount)(uid='"$1"'))' 'sshPublicKey')
attrLine=$(echo "$result" | sed -n '/^ /{H;d};/sshPublicKey:/x;$g;s/\n *//g;/sshPublicKey:/p')

if [[ "$attrLine" == sshPublicKey::* ]]; then
  echo "$attrLine" | sed 's/sshPublicKey:: //' | base64 -d
elif [[ "$attrLine" == sshPublicKey:* ]]; then
  echo "$attrLine" | sed 's/sshPublicKey: //'
else
  exit 1
fi
mbrgm
источник