Pam
Linix PAM
Это статья про полную хуйню ерунду - от руководства поставлена задача: заводить пользователя вида user@domain.tld на линукс-боксах. Из ограничений - такой пользователь нужен только один в системе.
В линуксе нельзя завести пользователя с символом "@" в имени стандартными средствами (--force варианты я не расматриваю). Потому для хранения пользователей нужно использовать какое-то внешнее хранилище.
Все написаное относится к CentOS 6.5 - меня интересовала именно эта система и со всякими вашими убунтами я не тестировал :)
С авторизацией по ключам в ssh РАБОТАТЬ НЕ БУДЕТ так как ssh не использует PAM для ключей
Решение
Первое что пришло в голову - использовать PAM и не заморачиваться с хранением пользователя вообще.
Сделать что то вроде такого в /etc/pam.d.sshd
auth sufficient pam_exec.so debug expose_authtok log=/root/pam_exec_debug.log /root/pam_exec.sh
Естественно /root/pam_exec.sh для моего пользователя (или для теста - всегда) возвращает "успех".
Это не сработало
Т.е. на уровне PAM это конечно же работает- но ssh слишком умный как утка и имеет дополнительную проверку - вызывая системную ф-ю getpwnam которая ничего не знает про PAM (а использует дедовские методы - /etc/passwd ... ) и не пускает с ошибкой:
Mar 5 17:52:55 test-vm-mm sshd[3378]: fatal: Internal error: PAM auth succeeded when it should have failed Mar 5 17:52:55 test-vm-mm sshd[3379]: fatal: mm_request_send: write: Broken pipe
После чтения кода sshd перевести на человеческий я зык это сообщение можно так "PAM сказал что пускать можно но т.к. поверка на наличие такого пользователя в системе дала отрицательный результат то мы все равно пускаем."
Отличный результат.
Для того что бы пользователь был доступен при проверке getpwnam это должен быть системный пользователь. Другого варианта нет.
Однако системные пользователи могут храниться не только в /etc/passwd но и в других местах
Тут возможно несколько вариантов
- LDAP
- NIS
- DB
Я остановлюсь на последнем - достаточно простое решение и не требует установки сторонних сервисов.
- Установить пакет nss_db-2.2.3-0.5.pre1.el6_5.1.x86_64 (версия может отличаться
- В файле /etc/nsswitch.conf включить использование bd
passwd: files db shadow: files db group: files db
- Отредактировать файл /var/db/Makefile что бы использовать не /etc/paswd, shadow и прочие, а свои файлы
- Сгенерировать базу (/usr/bin/make -f ./Makefile). Важно не забывать удалять старые базы перед перегенерацией.
Для проверки я сделал следующее:
- создал пользователя (useradd ...)
- сбекапил passwd shadow groups
- в копиях - оставил только этого нового пользователя
- из основной базы - его удалил (userdel ..), домашний каталог оставил.
После этого я смог успешно залогиниться в ssh с пользователем которого нет в /etc/passwd
Но и это не решает проблему - пользователь с "@" в имени остается не валидным.
PAM
Для того что бы пользователь маппился на другого (валидного) я применил простейшее решение - pam_regex.
Для примера я возьму вот такую регулярку:
auth required pam_regex.so debug extended transform=s/.*@.*/user1/g
Т.е. любой пользователь с @ будет мапиться на одного и того же пользователя.
в реальности это конечно же не нужно - маппить надо только того пользователя которого надо.
После чего у меня все заработало .
Сам модуль для PAM я брал здесь: http://puszcza.gnu.org.ua/software/pam-modules/manual/html_chapter/regex.html