UMGUM.COM 

Linux + LDAP Auth ( Наладка аутентификации пользователей Linux-системы посредством PAM через внешний LDAP-сервис. )

19 декабря 2019  (обновлено 14 июня 2020)

OS: "Linux Debian 8/9/10", "Linux Ubuntu 14/16/18 LTS".
Application: LDAP, NSS, PAM.

Задача: добавить возможность аутентификации через LDAP локальному пользователю операционной системы.

Представим себе небольшой набор linux-серверов, управляемых вручную (производство невелико и затраты на тотальную автоматизацию неоправданны), на которых должно быть всего два-три системных администратора. Традиционно посредством утилиты "useradd" в несущей операционной системе добавляется учётная запись, ей выделяется некий уровень привилегий посредством "sudo", создаётся пароль и таковой передаётся лично пользователю. Можно ли избежать последней компрометирующей процедуры, если в сети предприятия уже имеется сервис централизованной аутентификации - LDAP (или AD)?

Рассмотрим частный случай использования модуля подсистемы PAM, в самой минимальной его конфигурации, для решения поставленной задачи, следуя принципу минимально необходимой достаточности.


Обычно аутентификация в "Linux" реализуется посредством связки NSS (NSLCD, SSSD) и PAM. Подсистема NSS встраивается прослойкой между типовым интерфейсом (утилитами "useradd", "getent", etc.) и хранилищами сведений о пользователях (файлы конфигураций "passwd", "group", "shadow", etc.), предоставляя при этом дополнительные возможности вроде синхронизации атрибутов между разными хранилищами и автоматизации управления учётными записями. Подсистема PAM играет скромную и важную роль конечного аутентификатора как такового, а как раз только это нам и требуется для решения поставленной задачи.

Установка модулей PAM и настройка NSS.

В "Linux Ubuntu" при установке LDAP-модуля для PAM из системного APT-репозитория за единственно нужным пакетом "libpam-ldap" потянется большое количество вспомогательных скриптов ("auth-client-config", "ldap-auth-client", "ldap-auth-config"), нам не требующихся, но находящихся в строгой зависимости - как я ни пытался, корректно избавиться от них не получилось:

# apt-get install --no-install-recommends libpam-ldap ldap-utils

После развёртывания APT-дистрибутива автоматически запустится интерактивный конфигуратор и запросит подробности подключения к LDAP серверу - практической пользы от этого этапа нет, всё необходимое мы настроим далее вручную - так что отказываемся от всего предлагаемого и выбрасываем это из головы:

LDAP server Uniform Resource Identifier: ldapi:///
....
Distinguished name of the search base: dc=example,dc=net
....
LDAP version to use: 3
...
Make local root Database admin: no
....
Does the LDAP database require login?: no
....

Как выше упоминалось, в современном "Linux" аутентификация реализована через связку подсистем NSS и PAM. Наверное потому установка LDAP-модуля для PAM сборщиками APT-дистрибутивов была неразрывно связана с установкой LDAP-модуля и для NSS. Мы же здесь настраиваем лишь вспомогательную аутентификацию через LDAP посредством модулей PAM для уже имеющихся локальных пользователей, и не нуждаемся в помощи NSS при взаимодействии с LDAP.

Проследим, чтобы NSS не перехватывал запросы при обращении к LDAP, отрабатывая лишь в рамках типовых хранилищ "compat/files" и "systemd":

# cat /etc/nsswitch.conf

passwd:  compat systemd
group:   compat systemd
shadow:  compat
gshadow: files
....

Настройка аутентификации через LDAP.

LDAP-модуль подсистемы PAM работает через библиотеки "OpenLDAP". По умолчанию все его настройки собраны в одном конфигурационном файле:

# vi /etc/ldap.conf

# Параметры подключения к LDAP-сервису
uri ldaps://ldap0.example.net
port 636
ldap_version 3

# Указываем не проверять подпись SSL-сертификата сервера
tls_checkpeer no

# (опционально) Сервисная учётная запись для запроса атрибутов пользователя
#binddn uid=linux-auth,ou=accounts,ou=services,dc=example,dc=net
#bindpw ***

# Отправная точка и параметр глубины поиска
base ou=people,dc=example,dc=net
scope sub

# Фильтр в дополнение к встроенному "uid=%s"
#pam_filter objectclass=account

# Указываем атрибут, с которым сопоставляется имя пользователя
pam_login_attribute uid

# Отключаем запросы дополнительных атрибутов
pam_lookup_policy no
pam_check_host_attr no
pam_check_service_attr no

# Указываем не обрабатывать запросы для пользователей с "системными UID"
pam_min_uid 1000

Запрещаем чтение возможно содержащего пароль файла посторонними:

# chown root:root /etc/ldap.conf
# chmod go-rwx /etc/ldap.conf

При установке из дистрибутива LDAP-модуль для PAM включается автоматически, но для расширения кругозора можно сделать это повторно, указав подсистеме PAM использовать LDAP-модуль для аутентификации, помимо прочих возможных методов:

# pam-auth-update

PAM profiles to enable:
  [*] Unix authentication
  [*] LDAP Authentication
  [*] Register user sessions in the systemd control group hierarchy
  [ ] Create home directory on login
  [*] Inheritable Capabilities Management

После этого в файлах конфигурации "/etc/pam.d/common-account", "/etc/pam.d/common-auth", "/etc/pam.d/common-password", "/etc/pam.d/common-session" и "/etc/pam.d/common-session-noninteractive" появятся дополнительные строки указания на модуль LDAP-аутентификации, вроде нижеследующей:

# cat /etc/pam.d/common-auth

# here are the per-package modules (the "Primary" block)
auth  [success=2 default=ignore]  pam_unix.so nullok_secure
auth  [success=1 default=ignore]  pam_ldap.so use_first_pass
....

Для успешной аутентификации локального пользователя через удалённый LDAP достаточно включения соответствующего модуля только для этапов "common-account" и "common-auth" - а во всех остальных конфигурациях PAM её можно отключить, просто деактивировав строку с описанием модуля:

# vi /etc/pam.d/common-password

# here are the per-package modules (the "Primary" block)
password  [success=2 default=ignore]  pam_unix.so obscure sha512
#password  [success=1 user_unknown=ignore default=die]  pam_ldap.so use_authtok try_first_pass
....

Ограничение доступа перечнем локальных пользователей.

По умолчанию в операционную систему может зайти любой пользователь, успешно аутентифицировавшийся через LDAP посредством связки NSS и PAM. Однако нам требуется чёткий контроль за перечнем пользователей в локальной системе. Традиционно нежелательные пользователи отсеиваются списками доступа PAM или фильтрами LDAP-клиента, но самый простой, на мой взгляд, способ - запрет входа в систему для всех "нелокальных" пользователей.

Идея в том, что для обслуживания пользователя его учётную запись вначале потребуется создать явно, зарегистрировав в файле "/etc/passwd", и только после этого подсистема PAM станет с ним работать.

Достигается это добавлением строки указания загрузки модуля "pam_localuser.so", единственная роль которого - требовать наличия пользователя в локальной базе таковых:

# vi /etc/pam.d/common-account

....
# Require the presence of the user in the local list.
account required pam_localuser.so

После изменения параметров загрузки модулей PAM желательно запустить утилиту выстраивания взаимосвязей с учётом предустановленных профилей:

# pam-auth-update --force

Теперь даже при успешном прохождении аутентификации через LDAP вход в целевую операционную систему будет пресечён, если пользователь отсутствует в "/etc/passwd".

Соответственно, для обеспечения доступа в систему нужно явно создать локального пользователя:

# useradd -m user

Разрешаем пользователю переходить в роль суперпользователя:

# echo "user ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/user
# visudo -cf /etc/sudoers.d/user

Практика использования созданной схемы аутентификации.

Первый (и последующие, без ограничений) вход в целевую систему пользователь осуществляет с логином и паролем его учётной записи в LDAP:

$ ssh user@10.20.30.45

Сразу после первого входа желательно наладить аутентификацию по SSH-ключам, для чего потребуется создать соответствующую директорию, файл и разместить в последнем публичную часть SSH-ключа пользователя:

$ mkdir ~/.ssh
$ vi ~/.ssh/authorized_keys
$ chmod go-rwx ~/.ssh/authorized_keys

Теперь при последующем входе уже не понадобиться вводить пароль.

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

$ sudo su
# passwd user

Таким образом, пользователь как минимум имеет возможность войти в целевую систему с аутентификацией через внешний LDAP-сервис. При размещении публичной части SSH-ключа у пользователя появляется возможность входа без указания какого-либо пароля. А задав пароль для локальной учётной записи в целевой системе у пользователя появляется возможность входить в неё как с аутентификацией через внешний LDAP, так и с указанием локального пароля.

Пароль локальной учётной записи можно удалить:

# passwd -d user

Пользователь тоже может быть удалён, разумеется (в таком случае аутентификация через LDAP для него может быть успешной, но в систему вход будет закрыт из-за отсутствия пользователя в локальном перечне таковых в файле "/etc/passwd"):

# userdel user

Об атрибутах класса "posixAccount" в LDAP-записи.

В случае применения сервисов NSLCD или SSSD, а также типовой конфигурации NSS, для аутентификации пользователя linux-системы через LDAP в записях "каталога" требуется определение атрибутов класса "posixAccount".

Но, если синхронизация посредством NSS не используется, а задействована только аутентификация посредством PAM, то и атрибуты вроде "uidNumber" не являются обязательными (хотя и запрашиваются в процессе). Таким образом, описываемая в этой заметке схема аутентификации не нуждается в атрибутах "posixAccount".

Ссылки на используемые материалы.



Заметки и комментарии к публикации:


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )