В настоящее время я готовлю машину для службы веб-хостинга, и я решил использовать MySQL для хранения всех наших пользователей (поскольку остальные наши службы уже используют его). Для этого я использую libnss-mysql и pam-mysql. Однако, несмотря на то, что большая часть настройки работает, я столкнулся с проблемой при попытке изменить пароль пользователя с помощью passwd
.
На данный момент есть возможность создать пользователя (INSERT INTO
) и войдите как этот пользователь, используя su
. Машина не запрашивает пароль, и доступ к оболочке пользователя предоставляется напрямую. Однако как только я зарегистрируюсь как этот пользователь, passwd
заканчивается на:
$ passwd myuser
passwd: Authentication token manipulation error
passwd: password unchanged
Согласно журналам MySQL, запрос выполняется, когда passwd
вызывается, поэтому соединение с MySQL не является проблемой. Кроме того, когда я пытаюсь позвонить passwd
с несуществующим пользователем я получаю соответствующий passwd: user 'doesnotexist' does not exist
. passwd
находит пользователя, но не может изменять его информацию. В auth.log
файл журнала говорит:
pam_unix(passwd:chauthtok): user "myuser" does not exist in /etc/passwd
pam_mysql - option verbose is set to "1"
pam_mysql - pam_sm_chauthtok() called.
pam_mysql - pam_mysql_open_db() called.
pam_mysql - pam_mysql_open_db() returning 0.
pam_mysql - pam_sm_chauthtok() returning 0.
pam_mysql - pam_mysql_release_ctx() called.
pam_mysql - pam_mysql_destroy_ctx() called.
pam_mysql - pam_mysql_close_db() called.
При звонке passwd -Sa
чтобы получить статус всех аккаунтов, myuser
счет действительно появляется. Кроме, getent passwd
и getent shadow
оба возвращают действительную запись для myuser
.
$ passwd -Sa
...
messagebus L 06/28/2014 0 99999 7 -1
mysql L 06/28/2014 0 99999 7 -1
myuser P 01/01/1970 0 99999 7 -1
$ getent passwd myuser
myuser:x:5001:5000:First Last:/home/members/myuser:/bin/bash
$ getent shadow myuser
myuser:$6$...:0:0:99999:7:::0
Однако при запросе информации о старении myuser
:
$ chage -l myuser
chage: user 'myuser' does not exist in /etc/passwd
В целом :
su
находит пользователя и во всех случаях выполняет вход без пароля (если я root, в противном случае мне будет предложено ввести пароль и получить ошибку токена).chage
не может найти пользователя; кажется, ищет /etc/passwd
вместо БД.passwd
находит пользователя, но возвращает ошибку токена при попытке отредактировать его.Вот несколько примеров конфигурации:
/etc/pam.d/common-account
account sufficient pam_unix.so
account required pam_mysql.so config_file=/etc/pam-mysql.conf
/etc/pam.d/common-auth
auth sufficient pam_unix.so nullok_secure
auth required pam_mysql.so config_file=/etc/pam-mysql.conf
/etc/pam.d/common-session
session sufficient pam_unix.so
session required pwam_mysql.so config_file=/etc/pam-mysql.conf
/etc/pam.d/common-passwd
password sufficient pam_unix.so obscure sha512
password required pam_mysql.so config_file=/etc/pam-mysql.conf
/etc/libnss-mysql.cfg
getpwnam SELECT username,'x',(5000+id),5000,CONCAT(firstname, lastname),CONCAT('/home/members/', username),'/bin/bash' \
FROM users \
WHERE username='%1$s' \
LIMIT 1
getpwuid SELECT username,'x',(5000+id),5000,CONCAT(firstname, lastname),CONCAT('/home/members/', username),'/bin/bash' \
FROM users \
WHERE (5000+id)='%1$u' \
LIMIT 1
getspnam SELECT username,password,0,'0','99999','7','-1','-1','0' \
FROM users \
WHERE username='%1$s' \
LIMIT 1
getpwent SELECT username,'x',(5000+id),5000,CONCAT(firstname, lastname),CONCAT('/home/members/', username),'/bin/bash' \
FROM users
getspent SELECT username,password,0,'0','99999','7','-1','-1','0' \
FROM users
getgrnam SELECT '%1$s','members',5000
getgrgid SELECT name,password,'%1$u'
getgrent SELECT 'members','members',5000
memsbygid SELECT username \
FROM users
gidsbymem SELECT 5000
/bin/bash
для каждого.$HOME
каталог для myuser
является /home/members/myuser
.members
группа, GID которой 5000./etc/pam-mysql.conf
users.host = localhost
users.database = mydatabase
users.db_user = root
users.db_passwd = root_password
users.table = users
users.user_column = username
users.password_column = password
users.password_crypt = 1
/etc/nsswitch.conf
passwd: compat mysql
group: compat
shadow: compat mysql
Что пробовал:
$6$...
) в БД для myuser
.passwd -d
) : говорит мне myuser
нельзя найти в /etc/passwd
. То же самое происходит, если я пытаюсь заблокировать учетную запись или принудительно истечь срок действия пароля.passwd
из учетной записи root без изменений.su
): Я получаю сообщение об ошибке манипуляции токеном аутентификации и возвращаюсь к приглашению входа в систему. То же самое, когда я пытаюсь подключиться к SSH (плюс логические предупреждения об истечении срока действия пароля).Мне кажется, что Управление пользователями часть (учетная запись / сеанс?) правильно связана с MySQL, но управление паролями часть, кажется, частично полагается на /etc/passwd
. Я что-то упустил в конфигурации?
Хорошо, я нашел решение для этого. Первое: я настоятельно рекомендую всем, кто занимается этим, изучить Основы работы с модулями PAM. это действительно помогает понять все. Теперь давайте посмотрим на мою common-*
файлы. Все они имеют одинаковую структуру:
facility required pam_unix.so [...]
facility sufficient pam_mysql.so [...]
Теперь, когда я больше прочитал о модулях PAM, мне это кажется смешным. Вот некоторая документация о флагах управления PAM:
обязательный : если модуль завершается успешно, выполняется остальная часть цепочки, и запрос удовлетворяется, если какой-либо другой модуль не дает сбой. Если модуль выходит из строя, остальная часть цепочки также выполняется, но запрос в конечном итоге отклоняется.
достаточно : если модуль завершился успешно и ни один из предыдущих модулей в цепочке не отказал, цепочка немедленно прерывается и запрос удовлетворяется. Если модуль выходит из строя, модуль игнорируется и выполняется остальная часть цепочки.
По сути, моя конфигурация заставляет PAM вести себя следующим образом: аутентификация UNIX через /etc/passwd
и /etc/shadow
должен иметь успех во всех случаях. Поиск MySQL также будет выполнен, но если аутентификация UNIX не удалась, его результат не будет принят во внимание.
При такой настройке механизм аутентификации MySQL становится бесполезным во всех ситуациях. Правильная конфигурация будет:
facility sufficient pam_mysql.so [...]
facility required pam_unix.so [...]
Что говорит: Достаточно механизма аутентификации MySQL. Если это удастся, дальнейшие механизмы тестирования не подлежат. Однако в случае неудачи аутентификация UNIX должна быть успешной. Поскольку у меня будет больше пользователей MySQL, чем пользователей UNIX, логичнее сначала пройти аутентификацию по MySQL.
Также важно отметить разницу в ролях PAM и NSS. С моей настройкой аутентификация был полностью функциональным, так как конфигурация NSS была правильной. NSS обрабатывает базовую аутентификацию UNIX, но не управление учетной записью / сеансом, а также подключения к конкретным службам (SSH / FTP / ...). Всем этим занимается PAM. Это разделение является причиной того, что было возможно root
для подключения в качестве пользователя MySQL: NSS действительно нашел запись, и поскольку root
не требует аутентификации против чего-либо, чтобы получить идентификационные данные пользователя, модули PAM никогда не вызывались.