Установка и настройка OpenLDAP 2.4 в Ubuntu 14.04
Где работаем: ldap-client
Перейдём к настройке клиентской рабочей станции. Для начала установим необходимые пакеты:
# apt-get install ldap-utils libnss-ldapd libpam-ldapd
При установке нам будут предложены некоторые настройки . Далее мы всё равно внесём в конфигурацию изменения, но это нужно сделать, чтобы все пакеты нормально установились:
ldap://ldap-srv.example.com;dc=example,dc=com;group,netgroup,passwd,shadow.Прежде чем делать запросы к LDAP-серверу, проверим параметры клиента в /etc/ldap/ldap.conf:
BASE dc=example,dc=comURI ldap://ldap-srv.example.comTLS_CACERT /etc/ssl/certs/rootca.crtTLS_REQCERT demandTLS_CRLFILE /etc/ssl/rootca.crlTIMELIMIT 15TIMEOUT 20
Конечно, для того, чтобы всё заработало, сертификат нашего Certificate Authority (rootca.crt) и CRL-файл (rootca.crl) должны быть на месте.
Проверим работоспособность простым запросом. Результат опустим (Вы должны увидеть всё DIT):
$ ldapsearch -xZZLLLWD cn=nssproxy,ou=users,dc=example,dc=com Enter LDAP Password: dn: dc=example,dc=com ...
Поправим конфигурацию нашей локальной службы имён LDAP в файле /etc/nslcd.conf. Измените значение директивы bindpw на пароль записи cn=nssproxy,ou=users,dc=example,dc=com, который мы задавали ранее:
uid nslcdgid nslcduri ldap://ldap-srv.example.combase dc=example,dc=combinddn cn=nssproxy,ou=users,dc=example,dc=combindpw пароль.пользователя.nssproxyrootpwmoddn cn=admin,dc=example,dc=combase group ou=groups,dc=example,dc=combase passwd ou=users,dc=example,dc=combase shadow ou=users,dc=example,dc=combind_timelimit 5timelimit 10idle_timelimit 60ssl start_tlstls_reqcert allowtls_cacertfile /etc/ssl/certs/rootca.crtnss_initgroups_ignoreusers bin,daemon,games,lp,mail,nobody,nslcd,root,sshd,sync,uucpnss_initgroups_ignoreusers sys,man,news,proxy,www-data,backup,list,irc,gnats,landscape
Краткое описание использованных директив:
base мы сообщаем демону nslcd, где в DIT искать ту или иную информацию;bind_timelimit ограничивает время на установление соединения с сервером пятью секундами;timelimit устанавливает максимальное время ожидания ответа от сервера в 10 секунд;idle_timelimit заставит nslcd разорвать соединение с сервером, если в течении минуты в соединении не было никакой активности;ssl заставляет клиента использовать TLS при подключении к серверу;tls_reqcert и tls_cacertfile подобны директивам TLS_REQCERT и TLS_CACERT в конфигурации /etc/ldap/ldap.conf (необходимость проверки сертификата сервера и путь к корневому сертификату для выполнения проверки);nss_initgroups_ignoreusers описывает пользователей системы, поиск которых не нужно производить в DIT (чтобы мы могли работать с машиной при проблемах с доступом к серверу каталогов). В значение этой директивы следует внести имена всех общесистемных пользователей.Поменяем права доступа к nslcd.conf, потому что теперь в нём хранится информация для аутентификации:
# chmod 600 /etc/nslcd.conf # chown nslcd:nslcd /etc/nslcd.conf
Проверим содержимое /etc/nsswitch.conf:
passwd: compat ldapgroup: compat ldapshadow: compat ldaphosts: files dnsnetworks: filesprotocols: db filesservices: db filesethers: db filesrpc: db filesnetgroup: nis ldap
Убедимся в том, что демон nslcd запускается при старте системы и перезапустим его:
# update-rc.d nslcd defaults System start/stop links for /etc/init.d/nslcd already exist. # service nslcd restart * Starting LDAP connection daemon nslcd [ OK ]
Убедимся, что в системе ldap-client НЕТ учётной записи с именем nssproxy. Следующая команда должна выполняться без результата:
$ grep nssproxy /etc/passwd
Убедимся так же, что кэширующий демон службы имён загружается при старте системы и перезапустим его:
# update-rc.d nscd defaults System start/stop links for /etc/init.d/nscd already exist. # service nscd restart * Restarting Name Service Cache Daemon nscd ...done.
Сделаем пару запросов к LDAP-серверу, используя настроенную нами систему:
$ getent passwd test.user test.user:x:1101:1101:Test User:/home/test.user:/bin/bash $ getent group test.group test.group:*:1101:
Для того, чтобы проверить доступность информации о пароле потребуется выполнить getent от имени пользователя root:
# getent shadow test.user test.user:*:15140:0:99999:7:::0
Не беспокойтесь, хэш пароля мы видеть не должны.
Отлично, всё работает! Вышеприведённые результаты команд означают, что система ldap-client может осуществлять поиск по данным пользователей и групп в нашем каталоге OpenLDAP.
Создадим домашний каталог нашего тестового пользователя и установим для него права доступа:
# mkdir /home/test.user # chown test.user:test.group /home/test.user
Запустим в отдельном терминале вывод журнала аутентификации:
# tail -f /var/log/auth.log
В другом терминале выполним:
$ su - test.user
Мы должны получить приглашение командной строки пользователя test.user.
Теперь попробуем зайти на машину ldap-client по сети с использованием ssh под учётной записью test.user.
Демон ssh в конфигурации по-умолчанию должен работать с поддержкой PAM (и, соответственно, поддерживать аутентификацию через LDAP). Но на всякий случай приведём рабочую конфигурацию /etc/ssh/sshd_config:
Port 22Protocol 2HostKey /etc/ssh/ssh_host_rsa_keyHostKey /etc/ssh/ssh_host_dsa_keyHostKey /etc/ssh/ssh_host_ecdsa_keyHostKey /etc/ssh/ssh_host_ed25519_keyUsePrivilegeSeparation yesKeyRegenerationInterval 3600ServerKeyBits 1024LogLevel INFOLoginGraceTime 120PermitRootLogin without-passwordStrictModes yesRSAAuthentication yesPubkeyAuthentication yesIgnoreRhosts yesRhostsRSAAuthentication noHostbasedAuthentication noPermitEmptyPasswords noChallengeResponseAuthentication noX11Forwarding yesX11DisplayOffset 10PrintMotd noPrintLastLog yesTCPKeepAlive yesAcceptEnv LANG LC_*Subsystem sftp /usr/lib/openssh/sftp-serverUsePAM yesAddressFamily inetAllowGroups sysadmin test.groupSyslogFacility AUTHPRIVPasswordAuthentication yesAllowTcpForwarding noClientAliveInterval 120ClientAliveCountMax 2
Часть файла до пустой строки — конфигурация по-умолчанию. Далее — добавленное нами. Обратите внимание на строку с директивой AllowGroups. С помощью неё мы ограничиваем список групп пользователей, которые могут быть аутентифицированы через ssh. За информацией по остальным директивам обратитесь к документации.
Проверим работу с использованием какой-нибудь третьей машины. Например, выполним на нашем DNS-сервере (dns-srv):
$ ssh test.user@ldap-client.example.com Password: test.user@ldap-client:~$
Вывод последней команды сокращён. Если появляется приглашение командной строки, значит всё в порядке!
Где работаем: ldap-srv
Давайте заглянем в /var/log/slapd.log на нашем сервере. Мы можем обнаружить там следующие строки:
ldap-srv slapd[1304]: <= mdb_equality_candidates: (objectClass) not indexed ldap-srv slapd[1304]: <= mdb_equality_candidates: (uid) not indexed
С помощью следующей команды мы можем убедиться, что в нашем каталоге пока нет никаких индексов:
$ ldapsearch -xZZLLLWD cn=admin,dc=example,dc=com -b olcDatabase={1}mdb,cn=config olcDbIndex
Enter LDAP Password:
dn: olcDatabase={1}mdb,cn=config
Это значит, что в нашей базе данных надо создать индексы для атрибутов из журнала /var/log/slapd.log. Поэтому создадим ещё один LDIF-файл 5-posixAccount.indexes.ldif и запишем в него:
dn: olcDatabase={1}mdb,cn=configchangetype: modifyadd: olcDbIndexolcDbIndex: default pres,eq-add: olcDbIndexolcDbIndex: uid-add: olcDbIndexolcDbIndex: cn,sn pres,eq,sub-add: olcDbIndexolcDbIndex: objectClass eq-add: olcDbIndexolcDbIndex: memberUid eq-add: olcDbIndexolcDbIndex: uniqueMember eq-add: olcDbIndexolcDbIndex: uidNumber-add: olcDbIndexolcDbIndex: gidNumber eq
Зачем мелочиться? Укажем по-больше индексируемых атрибутов. И загрузим конфигурацию в наш каталог:
$ ldapadd -xZZWD cn=admin,dc=example,dc=com -f posixAccount.indexes.ldif
Enter LDAP Password:
modifying entry "olcDatabase={1}mdb,cn=config"
Проверим результат изменений:
$ ldapsearch -xZZLLLWD cn=admin,dc=example,dc=com -b olcDatabase={1}mdb,cn=config olcDbIndex
Enter LDAP Password:
dn: olcDatabase={1}mdb,cn=config
olcDbIndex: default pres,eq
olcDbIndex: uid
olcDbIndex: cn,sn pres,eq,sub
olcDbIndex: objectClass eq
olcDbIndex: memberUid eq
olcDbIndex: uniqueMember eq
olcDbIndex: uidNumber
olcDbIndex: gidNumber eq
Отлично! Теперь в журнале /var/log/slapd.log не должно быть ошибок.
Глава по обслуживанию в руководстве администратора OpenLDAP не слишком подробно описывает решаемые проблемы. Будем надеятся, что этот раздел поможет Вам.
Где работаем: ldap-srv
Что мы будем резервировать?
База данных и конфигурация сервера OpenLDAP могут быть выгружены в LDIF-файлы с помощью slapcat. Запакуем их вместе в один tar-файл. Общесистемная конфигурация — это всё остальное. Например, набор ключей Kerberos (keytab) и файл /etc/defaults/slapd.
Создадим файл для скрипта резервного копирования, и каталоги, куда мы будем складировать данные:
# mkdir -p /root/scripts /root/backup /var/log/backup # touch /root/scripts/backup.slapd.sh # chmod +x /root/scripts/backup.slapd.sh
И запишем в файл backup.slapd.sh несложный скрипт:
#!/bin/sh# Копируем данные и конфигурацию OpenLDAP в сжатые LDIF-файлы.# А так же резервируем весь каталог OpenLDAP и конфигурацию демона slapd.umask 022PATH="/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin"export PATHDATE=`date +%Y%m%d`BACKUP_DIR="/root/backup/slapd"BACKUP_DATA_FILENAME="slapd.data.${DATE}.ldif"BACKUP_CONFIG_FILENAME="slapd.config.${DATE}.ldif"BACKUP_TAR_FILENAME="slapd.directory.${DATE}.tar.gz"CA_TLS_CERT="/etc/ssl/certs/rootca.crt"DIT_CONFIG="cn=config"DIT_SUFFIX="dc=example,dc=com"SLAPD_CONFIG_FILENAME="/etc/default/slapd"SLAPD_DIR="/etc/ldap"SLAPD_LOG_ROTATION="/etc/logrotate.d/slapd"SLAPD_TLS_CERT="/etc/ldap/ssl/ldap-srv.example.com.crt"SLAPD_TLS_KEY="/etc/ldap/ssl/ldap-srv.example.com.key"SLAPCAT_OPTIONS="-F /etc/ldap/slapd.d"LOGFILE="/var/log/backup/slapd.log"KEEP="30"# Убедимся, что скрипт запущен от имени суперпользователяif [ `id -u` -ne "0" ]; thenecho "ERROR: only root can run this script." | tee -a ${LOGFILE}exit 1fi# Проверим, есть ли у нас файл для журналаif [ ! -f ${LOGFILE} ]; thentouch ${LOGFILE}if [ "$?" -ne "0" ]; thenecho "ERROR: could not create the log file."exit 1fifi# Убедимся, что у нас есть каталог для резервных копийif [ ! -d ${BACKUP_DIR} ]; thenmkdir -p ${BACKUP_DIR}if [ "$?" -ne "0" ]; thenecho "ERROR: could not create the backup directory." | tee -a ${LOGFILE}exit 1fifi# Убедимся, что в нашем каталоге с резервными копиями не свалено слишком много файлов# и удалим все резервные копии кроме последних ${KEEP} копий.FILES=`find ${BACKUP_DIR} -type f -name "slapd.*" -print | wc -l`if [ "${FILES}" -gt "${KEEP}" ]; thenOVER=`echo ${FILES}-${KEEP} | bc`RMFILES=`find ${BACKUP_DIR} -type f -name "slapd.*" -print | sort -r | tail -${OVER}`echo "NOTE: removing ${RMFILES} from the backup directory." >> ${LOGFILE}rm ${RMFILES}fi# Создаём резервную копию данных из DITslapcat ${SLAPCAT_OPTIONS} -b ${DIT_SUFFIX} -l ${BACKUP_DIR}/${BACKUP_DATA_FILENAME} >/dev/null 2>&1if [ "$?" -eq "0" ]; thengzip -f ${BACKUP_DIR}/${BACKUP_DATA_FILENAME} 2>&1 >> ${LOGFILE}if [ "$?" -ne "0" ] ; thenecho "ERROR: dump file compression problem." | tee -a ${LOGFILE}exit 1fielseecho "ERROR: problem running slapcat(8C) for the DIT data backup." | tee -a ${LOGFILE}rm ${BACKUP_DIR}/${BACKUP_DATA_FILENAME}exit 1fi# Сохраняем конфигурацию DIT в виде LDIF-файлаslapcat ${SLAPCAT_OPTIONS} -b ${DIT_CONFIG} -l ${BACKUP_DIR}/${BACKUP_CONFIG_FILENAME} >/dev/null 2>&1if [ "$?" -eq "0" ]; thengzip -f ${BACKUP_DIR}/${BACKUP_CONFIG_FILENAME} 2>&1 >> ${LOGFILE}if [ "$?" -ne "0" ] ; thenecho "ERROR: dump file compression problem." | tee -a ${LOGFILE}exit 1fielseecho "ERROR: problem running slapcat(8C) for the DIT config backup." | tee -a ${LOGFILE}rm ${BACKUP_DIR}/${BACKUP_CONFIG_FILENAME}exit 1fi# Делаем резервную копию файлов каталога и конфигурацииBACKUP_FILES_LIST="${CA_TLS_CERT} ${SLAPD_CONFIG_FILENAME} ${SLAPD_DIR} ${SLAPD_LOG_ROTATION} ${SLAPD_TLS_CERT} ${SLAPD_TLS_KEY}"tar zcf ${BACKUP_DIR}/${BACKUP_TAR_FILENAME} ${BACKUP_FILES_LIST} >/dev/null 2>&1if [ "$?" -ne "0" ]; thenecho "ERROR: problem running config directory tar." | tee -a ${LOGFILE}rm ${BACKUP_DIR}/${BACKUP_TAR_FILENAME}exit 1fi
Создадим задание планировщика cron для нашего скрипта:
# crontab -e
Откроется конфигурация планировщика для суперпользователя. Допишем в неё:
# Резервное копирование для OpenLDAP
00 22 * * * /root/scripts/backup.slapd.sh
По этому правилу резервное копирование запускается каждый день в 22:00. Запустите скрипт вручную или дождитесь и проверьте, что всё работает.
ВНИМАНИЕ! Копируйте файлы на другой сервер! Лучше всего монтировать сетевые ресурсы в каталоги резервного копирования (в нашем случае — в /root/backup). Тогда все данные сразу будут заливаться на удалённый сервер.
В случае выхода из строя сервера OpenLDAP у нас есть всё, чтобы его воскресить. Сценарий восстановления зависит от типа решаемой проблемы:
Где работаем: ldap-srv
Если сервер который крутит OpenLDAP сломается, то первым делом нам нужно будет найти другой или починить этот. Затем потребуется установить на него Ubuntu 14.04. Потом скопируйте на него файлы из резервной копии и выполните следующие команды:
# apt-get install -y slapd ldap-utils krb5-kdc-ldap krb5-pkinit krb5-admin-server libnss-ldapd libpam-ldapd wamerican sudo-ldap # mv /etc/ldap /etc/ldap.install # cd / && tar zxvf /tmp/slapd.directory.20141215.tar.gz # update-rc.d slapd defaults # service slapd start
Это поможет Вам начать работать. Конечно, затем нужно будет перенастроить rsyslog. Смотрите раздел 2.3.
Где работаем: ldap-srv
Чаще всего такое случается при настройке сервера. При изменении ACL Вы можете закрыть самим себе любой доступ к нему. Поправить ситуацию не сложно:
# service nslcd stop # service nscd stop # service slapd stop # mv /etc/ldap /etc/ldap.broken # cd / && tar zxvf /root/backup/slapd/slapd.directory.20141215.tar.gz # service slapd start # service nscd start # service nslcd start
Где работаем: ldap-srv
Чтож, иногда и администраторы совершают ошибки. В обычной ситуации достаточно просто запустить LDAP-браузер и вернуть всё как было. Но допустим один администратор в пятницу сделал изменение и уехал заниматься альпинизмом. Другой администратор не имел ни малейшего понятия об изменениях и в субботу после обеда мы имеем сломанную конфигурацию. В таких ситуациях у среднестатистического администратора нет терпения для отладки. Поэтому самый простой (и самый быстрый!) способ исправления ошибки — остановить демон slapd и вернуть данные из резервной копии, которая была сделана в четверг, с помощью slapadd.
# service nslcd stop # service nscd stop # service slapd stop # mv /var/lib/ldap /var/lib/ldap.broken # mkdir /var/lib/ldap # zcat /root/backup/slapd/slapd.data.20141212.ldif.gz > /tmp/slapd.data.ldif # slapadd -v < /tmp/slapd.data.ldif # chown -R openldap:openldap /var/lib/ldap # service slapd start # service nscd start # service nslcd start
Это вернёт данные из любого файла, в который мы сохраняли наши резервные копии.
Где работаем: ldap-srv
Вы ведь храните каталог /var в отдельной файловой системе (CCE-14777-7)? Иногда в нём кончается свободное место. Это может случиться как от разрастания базы данных в /var/lib/ldap, так и от слишком активного наполнения каталога /var/log журналами событий (подсказка: храните базу LDAP в отдельной ФС). Отсутствие свободного места будет генерировать ошибки в журналах. Используемый нами мехнизм манипуляции данными MDB не требует каких-либо особых процедур для восстановления из такого состояния. После вполне очевидного решения проблемы увеличения свободного места (lvresize / монтирование новой ФС / btrfs filesystem resize ) нужно просто перезапустить демоны:
# service slapd restart # service nscd restart # service nslcd restart
Вот и всё! Если пропали какие-то данные, просто восстановите их из резервной копии как описано в предыдущем разделе.
Для наших целей необходим настроенный DNS-сервер. Если в Вашей сети уже имеется DNS-сервер и он успешно разрешает имена для перечисленных выше машин, то пункт 1.1 можно пропустить. Помните об этом, если в последующих разделах Вы встретите упоминание о сервере DNS (dns-srv).
Где работаем: dns-srv
Настроим сеть в файле /etc/network/interfaces:
auto loiface lo inet loopbackauto eth0iface eth0 inet staticaddress 192.168.122.140netmask 255.255.255.0gateway 192.168.122.1dns-nameservers 192.168.122.1
Настроим имя DNS-сервера. В Ubuntu 14.04 останов или перезапуск сервиса networking не поддерживается, поэтому придётся сделать так:
# echo 'dns-srv.example.com' > /etc/hostname # reboot
Установим DNS сервер. Будем использовать простой dnsmasq:
# apt-get install dnsmasq
Убедимся, что он работает:
$ dig ubuntu.com @localhost | grep ^ubuntu.com
Должны получить примерно это:
ubuntu.com. 310 IN A 91.189.94.156
Настроим разрешение имён в файле /etc/hosts:
127.0.0.1 localhost192.168.122.140 dns-srv.example.com192.168.122.150 ldap-srv.example.com192.168.122.151 ldap-client.example.com
Где работаем: ldap-srv
Настроим сеть в файле /etc/network/interfaces:
auto loiface lo inet loopbackauto eth0iface eth0 inet staticaddress 192.168.122.150netmask 255.255.255.0gateway 192.168.122.1dns-nameservers 192.168.122.140
Настроим имя LDAP-сервера. В Ubuntu 14.04 останов или перезапуск сервиса networking не поддерживается, поэтому придётся сделать так:
# echo 'ldap-srv.example.com' > /etc/hostname # reboot
Проверим разрешение имени будущего сервера LDAP:
$ dig ldap-srv.example.com +short 192.168.122.150
Проверим обратное разрешение имени:
$ dig -x `dig ldap-srv.example.com +short` +short ldap-srv.example.com.
Где работаем: ldap-client
Настроим сеть в файле /etc/network/interfaces:
auto loiface lo inet loopbackauto eth0iface eth0 inet staticaddress 192.168.122.151netmask 255.255.255.0gateway 192.168.122.1dns-nameservers 192.168.122.140
Настроим имя LDAP-клиента. В Ubuntu 14.04 останов или перезапуск сервиса networking не поддерживается, поэтому придётся сделать так:
# echo 'ldap-client.example.com' > /etc/hostname # reboot
Проверим разрешение имени будущего клиента LDAP:
$ dig ldap-client.example.com +short 192.168.122.151
Проверим обратное разрешение имени:
$ dig -x `dig ldap-client.example.com +short` +short ldap-client.example.com.
Где работаем: ldap-srv
Прежде чем установить пакет sudo-ldap необходимо задать пароль для учетной записи root. Пакеты sudo и sudo-ldap взаимоисключающие, поэтому нужно перестраховаться, если с их установкой или работой случится беда.
# passwd Введите новый пароль UNIX: Повторите ввод нового пароля UNIX:
Теперь установим все необходимые пакеты. Мы сразу устанавливаем krb5-kdc-ldap и sudo-ldap, даже несмотря на то, что настроим их позже. Идея заключается в том, чтобы сразу получить необходимые схемы наборов данных OpenLDAP.
# apt-get install slapd ldap-utils krb5-kdc-ldap sudo-ldap
Во время установки Вам будет предложено задать некоторые настройки:
На данном этапе эти настройки не важны. Мы последовательно опишем их в дальнейшем.
Прежде чем продолжить, убедитесь, что нужные пакеты установились:
$ dpkg --get-selections|egrep '(slapd|ldap-utils|krb5-kdc-ldap|sudo-ldap)' krb5-kdc-ldap install ldap-utils install slapd install sudo-ldap install
Где работаем: ldap-srv
Инициализацию конфигурации каталога мы произведём с нуля с использованием нового подхода, OLC (cn=config).
Создайте каталог для работы со службой каталогов. У нас будет много конфигурационных файлов, неплохо бы класть их в одно место:
$ mkdir ~/ldap $ cd ~/ldap
Избавимся от установленных по-умолчанию конфигурации slapd и его базы данных:
# service slapd stop # rm -rf /etc/ldap/slapd.d # rm -rf /var/lib/ldap
Создадим пустой каталог для нашей новой конфигурации:
# mkdir /etc/ldap/slapd.d
Создадим файл 2.2-init-config.ldif с новой конфигурацией и запишем в него:
dn: cn=configobjectClass: olcGlobalcn: configolcPidFile: /var/run/slapd/slapd.pidolcArgsFile: /var/run/slapd/slapd.argsdn: olcDatabase={0}config,cn=configobjectClass: olcDatabaseConfigolcDatabase: {0}configolcAccess: to *by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" managedn: cn=schema,cn=configobjectClass: olcSchemaConfigcn: schema
В этом файле первым делом мы определяем корневую запись DIT (Directory Information Tree), cn=config. С помощью директив olcPidFile и olcArgsFile мы указали, куда необходимо записать ID процесса службы каталогов и аргументы его запуска соответственно.
Во втором разделе задаём служебную базу данных конфигурации cn=config. Мы так же добавили правило доступа (ACL, Access Control List), разрешающее манипулировать ей от имени пользователя root (uid=0, gid=0) с помощью механизма SASL EXTERNAL и идентификационной сущности IPC. Помните, что в конце каждого ACL, если не задан модификатор break, подразумевается наличие правила by * none . То есть остальной доступ к объекту в условии to — запрещён.
Последним разделом мы добавляем в конфигурацию контейнер для наборов схем данных.
Инициализируем конфигурацию:
# slapadd -n 0 -F /etc/ldap/slapd.d -l 2.2-init-config.ldif _#################### 100.00% eta none elapsed none fast! Closing DB...
Модификатор -n 0 говорит о том, что мы добавляем данные в базу данных с индексом 0, который зарезервирован для cn=config.
Проверим, всё ли в порядке с нашей конфигурацией:
# slaptest -uF /etc/ldap/slapd.d config file testing succeeded
Поправим права доступа, разрешив пользователю openldap заправлять в каталоге /etc/ldap/slapd.d:
# chown -R openldap:openldap /etc/ldap/slapd.d # chmod 750 /etc/ldap/slapd.d
Где работаем: ldap-srv
Разрешим нашей службе каталогов использовать только IPv4. Для этого установим SLAPD_OPTIONS="-4" в файле /etc/default/slapd. В остальном конфигурация стандартная:
SLAPD_CONF=SLAPD_USER="openldap"SLAPD_GROUP="openldap"SLAPD_PIDFILE=SLAPD_SERVICES="ldap:/// ldapi:///"SLAPD_SENTINEL_FILE=/etc/ldap/noslapdSLAPD_OPTIONS="-4"
Настроим rsyslog, чтобы он писал события службы каталогов в отдельный файл. Для этого достаточно добавить три строки в его конфигурацию после глобальных директив (/etc/rsyslog.conf):
$ModLoad imuxsock # provides support for local system logging$ModLoad imklog # provides kernel logging support$KLogPermitNonKernelFacility on$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat$RepeatedMsgReduction on$FileOwner syslog$FileGroup adm$FileCreateMode 0640$DirCreateMode 0755$Umask 0022$PrivDropToUser syslog$PrivDropToGroup syslog$WorkDirectory /var/spool/rsyslog$IncludeConfig /etc/rsyslog.d/*.conf# Пишем журнал демона slapd в /var/log/slapd.logif $programname == 'slapd' then /var/log/slapd.log& ~
Создадим файл для журнала службы каталогов и зададим для него права доступа. Затем перезапустим rsyslog, чтобы изменения вступили в силу:
# touch /var/log/slapd.log # chmod 0640 /var/log/slapd.log # chown syslog:adm /var/log/slapd.log # service rsyslog restart
Настроим logrotate для управления этим журналом. Создадим файл конфигурации /etc/logrotate.d/slapd и запишем в него:
/var/log/slapd.log {dailymissingokrotate 7compressdelaycompressnotifempty}
Проверим настройку logrotate:
# logrotate -df /etc/logrotate.conf
Наконец запускаем нашу службу каталогов:
# service slapd start * Starting OpenLDAP slapd [ OK ]
Заглянем в файл журнала slapd.log. Всё ли в порядке?
# tail /var/log/slapd.log ... slapd starting
Проверим, активен ли TCP порт 389:
$ ss -tan | grep 389 LISTEN 0 128 *:389 *:*
Убедимся, что UNIX сокет тоже активен:
$ ss -xa | grep ldap
u_str LISTEN 0 128 /var/run/slapd/ldapi 44345 * 0
Для пущей убедительности проверим текущую конфигурацию каталога с помощью ldapsearch:
# ldapsearch -QLLL -Y EXTERNAL -H ldapi:/// -b 'cn=config' dn
dn: cn=config
dn: cn=schema,cn=config
dn: olcDatabase={-1}frontend,cn=config
dn: olcDatabase={0}config,cn=config
Заметьте, что slapadd (из предыдущего пункта) добавил в наш каталог описание служебной базы данных frontend (в ней можно определить опции, которые будут применяться ко всем базам данных в текущей конфигурации OLC). Однако, если те же самые опции (в том числе правила ACL) определены в конкретной базе данных, то будут применяться именно они.
Где работаем: ldap-srv
Для работы нам понадобится два модуля. Один — для механизма базы данных mdb. На данный момент он рассматривается как основной для нормальных баз данных и должен прийти на смену bdb и hdb. Второй модуль — monitor, для создания и динамической поддержки ветки с информацией о текущем статусе демона slapd.
Чтобы их подключить нам понадобится всего один короткий LDIF-файл и специальная запись cn=module,cn=config. Назовём файл 2.4-add-modules.ldif и запишем в него:
dn: cn=module,cn=configobjectClass: olcModuleListcn: moduleolcModulePath: /usr/lib/ldapolcModuleLoad: back_mdb.laolcModuleLoad: back_monitor.la
Каталог с модулями в нашем случае — /usr/lib/ldap.
Добавим наш LDIF-файл в конфигурацию:
# ldapadd -QY EXTERNAL -H ldapi:/// -f 2.4-add-modules.ldif adding new entry "cn=module,cn=config"
Где работаем: ldap-srv
Прежде чем добавлять наборы схем данных в каталог, необходимо подготовить наборы схем из пакетов krb5-kdc-ldap и sudo-ldap к загрузке (перевести их в формат LDIF).
В используемой нами версии Ubuntu искомые наборы схем находятся здесь:
/usr/share/doc/sudo-ldap/schema.OpenLDAP /usr/share/doc/krb5-kdc-ldap/kerberos.schema.gz
Скопируем их во временный каталог:
$ zcat /usr/share/doc/krb5-kdc-ldap/kerberos.schema.gz > ~/ldap/kerberos.schema $ cp /usr/share/doc/sudo-ldap/schema.OpenLDAP ~/ldap/sudo.schema
На просторах сети был найден несложный скрипт для преобразования файлов schema в формат LDIF. Немного откорректируем его (для универсальности) и сохраним в том же каталоге ~/ldap под именем 2.5-schema-ldif.sh:
#!/bin/bashSCHEMAD=~/ldaptmpd=`mktemp -d`pushd ${tmpd} >>/dev/nullecho '' > convert.datfor schema in ${SCHEMAS} ; doecho include ${SCHEMAD}/${schema} >> convert.datdoneslaptest -f convert.dat -F .if [ $? -ne 0 ] ; thenecho "slaptest conversion failed"exitfifor schema in ${SCHEMAS} ; dofullpath=${SCHEMAD}/${schema}schema_name=`basename ${fullpath} .schema`schema_dir=`dirname ${fullpath}`ldif_file=${schema_name}.ldiffind . -name *${schema_name}.ldif -exec mv '{}' ./${ldif_file} \;sed -i "/dn:/ c dn: cn=${schema_name},cn=schema,cn=config" ${ldif_file}sed -i "/cn:/ c cn: ${schema_name}" ${ldif_file}sed -i '/structuralObjectClass/ d' ${ldif_file}sed -i '/entryUUID/ d' ${ldif_file}sed -i '/creatorsName/ d' ${ldif_file}sed -i '/createTimestamp/ d' ${ldif_file}sed -i '/entryCSN/ d' ${ldif_file}sed -i '/modifiersName/ d' ${ldif_file}sed -i '/modifyTimestamp/ d' ${ldif_file}sed -i '/^ *$/d' ${ldif_file}mv ${ldif_file} ${schema_dir}donepopd >>/dev/nullrm -rf $tmpd
Сделаем его исполняемым и запустим, передав через переменную SCHEMAS имена файлов конвертируемых наборов схем:
$ chmod +x 2.5-schema-ldif.sh $ SCHEMAS='kerberos.schema sudo.schema' 2.5-schema-ldif.sh config file testing succeeded
На выходе должны получить два набора схем данных в формате LDIF:
$ ls ~/ldap | egrep '(kerberos.ldif|sudo.ldif)' kerberos.ldif sudo.ldif
Переместим их в каталог к остальным наборам схем и поправим права доступа:
# mv ~/ldap/{kerberos.ldif,sudo.ldif} /etc/ldap/schema
# chown root:root /etc/ldap/schema/{kerberos.ldif,sudo.ldif}
# chmod 0644 /etc/ldap/schema/{kerberos.ldif,sudo.ldif}
Удалим не нужные больше наборы схем данных:
$ rm kerberos.schema sudo.schema
Создадим LDIF-файл с необходимыми нам наборами схем данных. Порядок их следования в файле очень важен! Атрибуты наборов схем иерархически связаны и требуют их объявления с соблюдением иерархии. Назовём файл 2.5-add-schemas.ldif и запишем в него:
include: file:///etc/ldap/schema/core.ldifinclude: file:///etc/ldap/schema/cosine.ldifinclude: file:///etc/ldap/schema/inetorgperson.ldifinclude: file:///etc/ldap/schema/collective.ldifinclude: file:///etc/ldap/schema/corba.ldifinclude: file:///etc/ldap/schema/duaconf.ldifinclude: file:///etc/ldap/schema/openldap.ldifinclude: file:///etc/ldap/schema/dyngroup.ldifinclude: file:///etc/ldap/schema/java.ldifinclude: file:///etc/ldap/schema/misc.ldifinclude: file:///etc/ldap/schema/nis.ldifinclude: file:///etc/ldap/schema/ppolicy.ldifinclude: file:///etc/ldap/schema/kerberos.ldifinclude: file:///etc/ldap/schema/sudo.ldif
Последними строчками мы указали получившиеся в результате конвертации наборы схем kerberos.ldif и sudo.ldif.
Добавим наши наборы схем:
# ldapadd -QY EXTERNAL -H ldapi:/// -f 2.5-add-schemas.ldif adding new entry "cn=core,cn=schema,cn=config" adding new entry "cn=cosine,cn=schema,cn=config" adding new entry "cn=inetorgperson,cn=schema,cn=config" adding new entry "cn=collective,cn=schema,cn=config" adding new entry "cn=corba,cn=schema,cn=config" adding new entry "cn=duaconf,cn=schema,cn=config" adding new entry "cn=openldap,cn=schema,cn=config" adding new entry "cn=dyngroup,cn=schema,cn=config" adding new entry "cn=java,cn=schema,cn=config" adding new entry "cn=misc,cn=schema,cn=config" adding new entry "cn=nis,cn=schema,cn=config" adding new entry "cn=ppolicy,cn=schema,cn=config" adding new entry "cn=kerberos,cn=schema,cn=config" adding new entry "cn=sudo,cn=schema,cn=config" adding new entry "cn=autofs,cn=schema,cn=config"
Где работаем: ldap-srv
Вот мы и подошли к созданию базы данных, в которой будем хранить нашу рабочую информацию.
Для начала создадим пароль администратора. Утилита slappasswd генерирует посоленный хэш вводимого нами пароля:
# slappasswd -h '{SSHA}'
New password:
Re-enter new password:
{SSHA}RMjrfsi7NkpBMR+NQHTDk4iddvo/2le+
Не забудьте сам пароль! :)
Сформируем конфигурационный LDIF-файл для нашей базы данных (2.6-db.ldif) и запишем получившийся хэш в атрибут olcRootPW:
dn: olcDatabase=mdb,cn=configobjectClass: olcMdbConfigolcDatabase: mdbolcSuffix: dc=example,dc=comolcDbDirectory: /var/lib/ldapolcDbMaxsize: 1073741824olcRootDN: cn=admin,dc=example,dc=comolcRootPW: {SSHA}RMjrfsi7NkpBMR+NQHTDk4iddvo/2le+olcAccess: {0}to *by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manageby * breakolcAccess: {1}to attrs=userPasswordby self writeby anonymous autholcAccess: {2}to *by self readdn: olcDatabase=monitor,cn=configobjectClass: olcDatabaseConfigolcDatabase: monitor
И вновь несколько комментариев...
dc=example,dc=com.olcDbDirectory мы указали путь к каталогу бузы данных. Атрибут обязательный и требует существование каталога на момент загрузки в базу данных.olcRootDN мы записываем DN администратора нашей базы данных.olcRootDN, задавать правило в ACL не нужно, он обладает полным доступом к данным в вашей базе. Поэтому постарайтесь сохранить его пароль в надежном месте (например, используя keepass или gpg).by.userPassword:
monitor).Для нашей базы данных необходимо создать каталог и задать ему права доступа:
# mkdir /var/lib/ldap # chown openldap:openldap /var/lib/ldap # chmod 0700 /var/lib/ldap
Загрузим конфигурацию базы данных:
# ldapadd -QY EXTERNAL -H ldapi:/// -f 2.6-db.ldif adding new entry "olcDatabase=mdb,cn=config" adding new entry "olcDatabase=monitor,cn=config"
Определим RootDN для доступа к конфигурации службы каталогов. Он будет ссылаться на RootDN, находящийся в нашей БД. Эта запись желательна только при первоначальной настройке или в тестовой конфигурации. Не оставляйте её в боевой системе! Для {-1}frontend зададим минимально необходимые права для доступа к RootDSE. Создадим LDIF-файл 2.6-acl-mod.ldif, модифицирующий права доступа:
dn: olcDatabase={0}config,cn=configchangetype: modifyadd: olcRootDNolcRootDN: cn=admin,dc=example,dc=comdn: olcDatabase={-1}frontend,cn=configchangetype: modifyadd: olcAccessolcAccess: {0}to *by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manageby * breakolcAccess: {1}to dn.base=""by * readolcAccess: {2}to dn.base="cn=subschema"by * read
Загрузим LDIF, изменяющий ACL:
# ldapadd -QY EXTERNAL -H ldapi:/// -f 2.6-acl-mod.ldif
modifying entry "olcDatabase={-1}frontend,cn=config"
modifying entry "olcDatabase={0}config,cn=config"
Теперь мы ещё больше повысили значимость учётной записи администратора. С её помощью теперь можно получить полный доступ к службе каталогов. Имейте это ввиду. :)
Проверим корректность всех ACL и, заодно, наличие всех добавленных нами данных (вывод отформатирован для наглядности):
# ldapsearch -QLLL -Y EXTERNAL -H ldapi:/// -b 'cn=config' dn olcAccess
dn: cn=config
dn: cn=module{0},cn=config
dn: cn=schema,cn=config
dn: cn={0}core,cn=schema,cn=config
dn: cn={1}cosine,cn=schema,cn=config
dn: cn={2}inetorgperson,cn=schema,cn=config
dn: cn={3}collective,cn=schema,cn=config
dn: cn={4}corba,cn=schema,cn=config
dn: cn={5}duaconf,cn=schema,cn=config
dn: cn={6}openldap,cn=schema,cn=config
dn: cn={7}dyngroup,cn=schema,cn=config
dn: cn={8}java,cn=schema,cn=config
dn: cn={9}misc,cn=schema,cn=config
dn: cn={10}nis,cn=schema,cn=config
dn: cn={11}ppolicy,cn=schema,cn=config
dn: cn={12}kerberos,cn=schema,cn=config
dn: cn={13}sudo,cn=schema,cn=config
dn: olcDatabase={-1}frontend,cn=config
olcAccess: {0}to *
by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external ,cn=auth manage
by * break
olcAccess: {1}to dn.base=""
by * read
olcAccess: {2}to dn.base="cn=subschema"
by * read
dn: olcDatabase={0}config,cn=config
olcAccess: {0}to *
by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external ,cn=auth" manage
dn: olcDatabase={1}mdb,cn=config
olcAccess: {0}to *
by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external ,cn=auth" manage
by * break
olcAccess: {1}to attrs=userPassword
by self write
by anonymous auth
olcAccess: {2}to *
by self read
dn: olcDatabase={2}monitor,cn=config
Убедимся, что учётная запись администратора имеет доступ к нашей службе каталогов:
$ ldapwhoami -WD cn=admin,dc=example,dc=com Enter LDAP Password: dn:cn=admin,dc=example,dc=com
Отлично! Теперь у нас есть работающий сервер OpenLDAP.
Отредактируем файл /etc/ldap/ldap.conf. Это нужно только для того, чтобы немного упростить себе жизнь и меньше печатать в дальнейшем. В BASE подставьте свой суффикс, а в URI — FQDN Вашего сервера OpenLDAP:
BASE dc=example,dc=comURI ldap://ldap-srv.example.com# TLS_CACERT /etc/ssl/certs/rootca.crt# TLS_REQCERT demandTIMELIMIT 15TIMEOUT 20
С настройкой TLS мы разберемся в следующем разделе.
И последний штрих. Добавим демон нашей службы каталогов в автозагрузку:
# update-rc.d slapd defaults
Это руководство является вольным переводом. Исходная конфигурация для CentOS 6.2 адаптирована под Ubuntu 14.04 server. Выражаю благодарность автору оригинала и привожу ссылку:
Another IT blog: HOWTO: CentOS 6.2 OpenLDAP 2.4 Setup (EN)
В процессе написания использовались материалы проекта pro-ldap.ru. В том числе:
Несколько весьма полезных ссылок для понимания сути описанного далее:
OpenLDAP Software 2.4 Administrator's Guide (EN)
Руководство администратора OpenLDAP 2.4 (RU)
LDAP для учёных-ракетчиков (RU)
Конфигурация используемых в нашем стенде машин:
На всех машинах при установке ОС заводится пользовательская учётная запись user.
| Шлюз | 192.168.122.1 |
| Сервер DNS | |
| hostname: | dns-srv.example.com |
| ip: | 192.168.122.140 |
| Сервер каталогов и сервер Kerberos | |
| hostname: | ldap-srv.example.com |
| ip: | 192.168.122.150 |
| Клиентская машина | |
| hostname: | ldap-client.example.com |
| ip: | 192.168.122.151 |
| Сервер NFS | |
| hostname: | nfs-srv.example.com |
| ip: | 192.168.122.154 |
| Сервер репликации | |
| hostname: | ldap-srv-repl.example.com |
| ip: | 192.168.122.160 |
Начните с установки Ubuntu 14.04. Это довольно просто. Для этого примера я использовал виртуальные машины. Постарайтесь воздержаться от установки большого количества пакетов. Такой подход уменьшит количество обновляемых пакетов, а так же сузит перечень возможных атак на Ваши серверы. После первоначальной установки каждой виртуальной машины обновите программное обеспечение командой:
# apt-get update && apt-get upgrade
Для тех, кто не в курсе... В тексте обращайте внимание на символы # и $. Идущие после них команды выполняются от имени пользователя root и обычного пользователя соответственно. Выбор за Вами, открывать отдельный терминал с правами суперпользователя или предварять команды командой sudo в терминале обычного пользователя.
В этом разделе мы научимся использовать OpenLDAP 2.4 в качестве хранилища принципалов (principals) Kerberos и разберем, как настраивать клиентские рабочие станции. Kerberos — это сетевой протокол, который работает на основе билетов (tickets) и позволяет передавать данные через незащищённые сети для безопасной идентификации и аутентификации. Его дизайн преимущественно опирается на клиент-серверную модель и позволяет произвести взаимную аутентификацию субъекта и объекта доступа. Сообщения протокола устойчивы к прослушиванию и атакам повтора. Kerberos работает на основе криптографии с симметричным ключом и требует наличия доверенной третьей стороны, а так же может применяться с использованием криптографии с открытым ключом на некоторых этапах процесса аутентификации.
В этом руководстве в роли сервера Kerberos будем использовать ldap-srv. Но ничто не мешает Вам использовать для этого отдельную машину.
Где работаем: ldap-srv
Включите NTP и убедитесь, что сервер и клиенты синхронизированы! Мы не будем описывать, как настраивать NTP. Вы можете найти множество примеров в сети, если потребуется.
Теперь, когда наш сервер OpenLDAP настроен, мы можем приступить к конфигурированию сервера Kerberos. В этом разделе мы опишем, как развернуть центр распределения ключей Kerberos (KDC, Key Distribution Center) для области (realm) EXAMPLE.COM. Начнём с установки необходимых пакетов. В процессе будет так же установлено несколько пакетов-зависимостей. Пакет wamerican создаст файл /usr/share/dict/words, используемый kadmind. Вместо него можно использовать любой другой словарь или несколько словарей. Чтобы посмотреть их список, посмотрите содержимое метапакета wordlist.
# apt-get install krb5-kdc krb5-pkinit krb5-admin-server wamerican libsasl2-modules-gssapi-mit
В разделе 2.5 мы уже установили схему Kerberos для OpenLDAP сервера, но давайте лишний раз убедимся, что она на месте:
# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b cn=schema,cn=config dn | grep -i kerberos
dn: cn={12}kerberos,cn=schema,cn=config
Схема на месте. В ней содержится достаточно много объектов. Чтобы посмотреть их все, используйте следующий запрос:
# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b cn={12}kerberos,cn=schema,cn=config | grep NAME | cut -d' ' -f5 | sort
Эта команда должна вернуть список объектов. Это важно, потому что если новых атрибутов Kerberos LDAP нет, то kdb5_ldap_util(8) выдаст следующую ошибку:
kdb5_ldap_util: Kerberos Container create FAILED: No such object while creating realm 'EXAMPLE.COM'
Итак, у нас есть набор схемы данных и объекты. Но есть ли у нас контейнер для принципалов Kerberos?
# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b ou=services,dc=example,dc=com dn | grep -i kerberos
Нет, нету. Создадим его, а заодно — пользователя и группу, которые будут использоваться Kerberos для взаимодействия с сервером OpenLDAP. Используем для этой цели вот такой LDIF-файл 9.1-kerberos.ldif:
# Создадим контейнер для Kerberosdn: cn=kerberos,ou=services,dc=example,dc=comcn: kerberosobjectClass: topobjectClass: krbContainer# Добавим группу krbadmindn: cn=krbadmin,ou=groups,dc=example,dc=comobjectClass: topobjectClass: posixGroupcn: krbadmingidNumber: 800description: Kerberos administrator's group.# Добавим пользователя krbadmindn: cn=krbadmin,ou=users,dc=example,dc=comobjectClass: inetOrgPersonobjectClass: organizationalPersonobjectClass: personobjectClass: posixAccountobjectClass: topcn: krbadmingivenName: Kerberos Administratormail: kerberos.admin@example.comsn: krbadminuid: krbadminuidNumber: 800gidNumber: 800homeDirectory: /home/krbadminloginShell: /bin/falsedisplayname: Kerberos Administrator
Загрузим этот файл в базу данных нашего сервера каталогов:
$ ldapadd -xZZWD cn=admin,dc=example,dc=com -f ~/ldap/9.1-kerberos.ldif Enter LDAP Password: adding new entry "cn=kerberos,ou=services,dc=example,dc=com" adding new entry "cn=krbadmin,ou=groups,dc=example,dc=com" adding new entry "cn=krbadmin,ou=users,dc=example,dc=com"
Зададим пароль для пользователя krbadmin. Сохраните пароль в надежном месте (например, используя keepass или gpg).
$ ldappasswd -xZZWSD "cn=admin,dc=example,dc=com" "cn=krbadmin,ou=users,dc=example,dc=com"
Создадим конфигурационный файл Kerberos /etc/krb5.conf:
[logging]default = SYSLOG:INFO:LOCAL1kdc = SYSLOG:NOTICE:LOCAL1admin_server = SYSLOG:WARNING:LOCAL1[libdefaults]default_realm = EXAMPLE.COMdns_lookup_realm = falsedns_lookup_kdc = falseticket_lifetime = 24hrenew_lifetime = 7dforwardable = true[realms]EXAMPLE.COM = {kdc = ldap-srv.example.comadmin_server = ldap-srv.example.comdefault_domain = example.comdatabase_module = openldap_ldapconf}[domain_realm].example.com = EXAMPLE.COMexample.com = EXAMPLE.COM[appdefaults]pam = {debug = falseticket_lifetime = 36000renew_lifetime = 36000forwardable = truekrb4_convert = false}[dbmodules]openldap_ldapconf = {db_library = kldapldap_kerberos_container_dn = cn=kerberos,ou=services,dc=example,dc=comldap_kdc_dn = cn=krbadmin,ou=users,dc=example,dc=com# этот объект должен иметь права на чтение контейнера области,# контейнера принципала и поддеревьев областиldap_kadmind_dn = cn=krbadmin,ou=users,dc=example,dc=com# этот объект должен иметь права на чтение контейнера области,# контейнера принципала и поддеревьев областиldap_service_password_file = /etc/krb5.d/stash.keyfileldap_servers = ldapi:///ldap_conns_per_server = 5}
Теперь создадим список контроля доступа (ACL) администратора Kerberos. Не путайте этот ACL с ACL OpenLDAP. Это не одно и то же. Чуть ниже мы поработаем с ACL для OpenLDAP. Создадим файл /etc/krb5kdc/kadm5.acl с таким содержимым:
*/admin@EXAMPLE.COM *
Отредактируем /etc/krb5kdc/kdc.conf, конфигурационный файл службы аутентификации (AS, Authentication Service) и центра распределения ключей (KDC):
[kdcdefaults]kdc_ports = 88kdc_tcp_ports = 88[realms]EXAMPLE.COM = {#master_key_type = aes256-ctsacl_file = /etc/krb5kdc/kadm5.acldict_file = /usr/share/dict/wordsadmin_keytab = /etc/krb5kdc/kadm5.keytabsupported_enctypes = aes256-cts:normal aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal}
В отдельном терминале включите просмотр журнала сервера OpenLDAP. Так мы сможем увидеть сообщения, генерируемые командой kdb5_ldap_util(8):
# tail -F /var/log/slapd.log
Создайте каталог-тайник для пароля. В файле /etc/krb5.conf он указан в переменной ldap_service_password_file:
# mkdir /etc/krb5.d # chmod u=rwx,g=,o= /etc/krb5.d
Извлеките пароль пользователя cn=krbadmin,ou=users,dc=example,dc=com, используя kdb5_ldap_util(8):
# kdb5_ldap_util -D "cn=admin,dc=example,dc=com" stashsrvpw -f /etc/krb5.d/stash.keyfile cn=krbadmin,ou=users,dc=example,dc=com
Вам будет предложено ввести мастер-пароль базы данных. Очень важно, чтобы Вы НЕ ЗАБЫЛИ этот пароль!
В основном терминале выполните следующую команду для добавления записей Kerberos в базу данных OpenLDAP:
# kdb5_ldap_util -D "cn=admin,dc=example,dc=com" create -subtrees "cn=kerberos,ou=services,dc=example,dc=com" -r EXAMPLE.COM -s
Вышеуказанная команда создаст несколько записей в cn=kerberos,ou=services,dc=example,dc=com. Чтобы увидеть их, выполните запрос:
# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b cn=kerberos,ou=services,dc=example,dc=com dn
Но может ли кто-нибудь кроме пользователя cn=admin увидеть нашу информацию Kerberos? Это было-бы не очень мудро. Поэтому давайте взглянём на ACL нашего сервера OpenLDAP:
# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b olcDatabase={1}mdb,cn=config olcAccess
Что нам надо сделать, так это дать права доступа на чтение/запись администратору Kerberos (cn=krbadmin,ou=users,dc=example,dc=com) к поддереву cn=kerberos,ou=services,dc=example,dc=com. Никакой другой пользователь не должен иметь доступа к этой информации (за исключением администратора каталога).
Для этого сформируем LDIF-файл 9.1-kerberos.acl.ldif:
dn: olcDatabase={1}mdb,cn=configchangetype: modifyreplace: olcAccessolcAccess: {0}to *by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manageby * breakolcAccess: {1}to attrs=userPassword,userPKCS12by self writeby anonymous autholcAccess: {2}to attrs=shadowLastChangeby self writeolcAccess: {3}to dn.subtree="cn=kerberos,ou=services,dc=example,dc=com"by dn.exact="cn=krbadmin,ou=users,dc=example,dc=com" manageolcAccess: {4}to *by dn.base="cn=nssproxy,ou=users,dc=example,dc=com" readby self read
Загрузим данные в сервер каталогов:
# ldapmodify -QY EXTERNAL -H ldapi:/// -f 9.1-kerberos.acl.ldif
Убедитесь, что новые ACL работают. Суперпользователь и пользователь cn=admin,dc=example,dc=com должны иметь доступ к поддереву cn=kerberos,ou=services,dc=example,dc=com. Пользователь cn=nssproxy,ou=users,dc=example,dc=com не сможет обнаружить само существование контейнера Kerberos, а cn=krbadmin,ou=users,dc=example,dc=com должен не только видеть контейнер, но и иметь для него права на чтение/запись. Мы так же должны убедиться, что обычные пользователи всё ещё могут использовать сервер OpenLDAP для аутентификации и что они могут менять себе пароли.
Этот запрос возвращает поддерево cn=kerberos,ou=services,dc=example,dc=com:
$ ldapsearch -xZZLLLWD cn=krbadmin,ou=users,dc=example,dc=com -b cn=kerberos,ou=services,dc=example,dc=com dn
Следующий запрос должен завершиться с ошибкой No such object (32):
$ ldapsearch -xZZLLLWD cn=nssproxy,ou=users,dc=example,dc=com -b cn=kerberos,ou=services,dc=example,dc=com dn
Теперь с клиентской машины убедимся, что пользователь, учётная запись которого хранится на сервере каталогов, может менять свой пароль:
Где работаем: ldap-client
$ su - test.user $ passwd (current) LDAP Password: Новый пароль : Повторите ввод нового пароля : passwd: password updated successfully
Где работаем: ldap-srv
Настало время настроить журналирование. Для начала добавим в конфигурацию rsyslog следующие строки (/etc/rsyslog.conf):
...# Пишем журнал демона krb5-kdc в /var/log/krb5kdc.log:if $programname == 'krb5kdc' then /var/log/krb5kdc.log& ~# Пишем журнал демона krb5-admin-server в /var/log/kadmind.log:if $programname == 'kadmind' then /var/log/kadmind.log& ~
Создадим файлы журналов и зададим для них права доступа:
# touch /var/log/{krb5kdc,kadmind}.log
# chmod 0640 /var/log/{krb5kdc,kadmind}.log
# chown syslog:adm /var/log/{krb5kdc,kadmind}.log
Настроим logrotate. Создадим два конфигурационных файла.
Файл /etc/logrotate.d/krb5kdc для демона krb5-kdc:
/var/log/krb5kdc.log {dailymissingokrotate 7compressdelaycompressnotifempty}
Файл /etc/logrotate.d/kadmind для демона krb5-admin-server:
/var/log/kadmind.log {dailymissingokrotate 7compressdelaycompressnotifempty}
Перезапустим демон rsyslog, чтобы конфигурация вступила в силу. Добавим демоны krb5-kdc и krb5-admin-server в автоматический запуск, затем запустим их:
# service rsyslog restart # update-rc.d krb5-kdc defaults # update-rc.d krb5-admin-server defaults # service krb5-kdc start # service krb5-admin-server start
Загляните в журнал /var/log/krb5kdc.log. Вы должны увидеть там подобную строку:
...
Dec 1 15:49:54 ldap-srv krb5kdc[1992]: commencing operation
Проверим, что наши демоны слушают необходимые порты. Порт 88 (krb5kdc), порты 464 и 749 (kadmind):
$ ss -tan | egrep ':88|:464|:749' LISTEN 0 2 *:749 *:* LISTEN 0 5 *:464 *:* LISTEN 0 5 *:88 *:*
Поздравляю, теперь у Вас есть рабочий сервер аутентификации (AS) и сервер распределения ключей (KDC) MIT Kerberos 5!
Что дальше? В первую очередь нам необходимо создать принципал для локального сервера. Затем — принципал для пользователя test.user. Сделаем это так (разобъём вывод на части, чтобы добавить комментарии):
# kadmin.local Authenticating as principal root/admin@EXAMPLE.COM with password.
Здесь мы создаём принципал машины для текущего сервера (на котором залогинены). Далее жирный шрифт — вводимый нами текст:
kadmin.local: addprinc -randkey host/ldap-srv.example.com@EXAMPLE.COM WARNING: no policy specified for host/ldap-srv.example.com@EXAMPLE.COM; defaulting to no policy Principal "host/ldap-srv.example.com@EXAMPLE.COM" created.
После создания принципала сервера мы можем добавить его в набор ключей Kerberos (/etc/krb5.keytab):
kadmin.local: ktadd host/ldap-srv.example.com@EXAMPLE.COM Entry for principal host/ldap-srv.example.com@EXAMPLE.COM with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab. Entry for principal host/ldap-srv.example.com@EXAMPLE.COM with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab. Entry for principal host/ldap-srv.example.com@EXAMPLE.COM with kvno 2, encryption type des3-cbc-sha1 added to keytab FILE:/etc/krb5.keytab. Entry for principal host/ldap-srv.example.com@EXAMPLE.COM with kvno 2, encryption type arcfour-hmac added to keytab FILE:/etc/krb5.keytab. Entry for principal host/ldap-srv.example.com@EXAMPLE.COM with kvno 2, encryption type des-hmac-sha1 added to keytab FILE:/etc/krb5.keytab. Entry for principal host/ldap-srv.example.com@EXAMPLE.COM with kvno 2, encryption type des-cbc-md5 added to keytab FILE:/etc/krb5.keytab.
Следующим шагом создадим принципал для моего пользователя pablo и зададим для него пароль:
kadmin.local: addprinc pablo@EXAMPLE.COM WARNING: no policy specified for pablo@EXAMPLE.COM; defaulting to no policy Enter password for principal "pablo@EXAMPLE.COM": Re-enter password for principal "pablo@EXAMPLE.COM": Principal "pablo@EXAMPLE.COM" created.
Теперь создадим принципал пользователя с правами администратора. Помните файл /etc/krb5kdc/kadm5.acl? Вот где он вступает в игру. С помощью этого файла пользователи с префиксом /admin имеют права администратора на доступ к области Kerberos. Это значит, что они могут создавать и удалять записи пользователей и политики доступа. Поэтому убедитесь, что Вы знаете этих пользователей и доверяете им!
kadmin.local: addprinc pablo/admin@EXAMPLE.COM WARNING: no policy specified for pablo/admin@EXAMPLE.COM; defaulting to no policy Enter password for principal "pablo/admin@EXAMPLE.COM": Re-enter password for principal "pablo/admin@EXAMPLE.COM": Principal "pablo/admin@EXAMPLE.COM" created.
Посмотрим список текущих принципалов в области:
kadmin.local: get_principals K/M@EXAMPLE.COM krbtgt/EXAMPLE.COM@EXAMPLE.COM kadmin/admin@EXAMPLE.COM kadmin/changepw@EXAMPLE.COM kadmin/history@EXAMPLE.COM kadmin/ldap-srv.example.com@EXAMPLE.COM host/ldap-srv.example.com@EXAMPLE.COM pablo@EXAMPLE.COM pablo/admin@EXAMPLE.COM
А эта команда выведет подробную информацию о принципале host/ldap-srv.example.com@EXAMPLE.COM:
kadmin.local: getprinc host/ldap-srv.example.com@EXAMPLE.COM Principal: host/ldap-srv.example.com@EXAMPLE.COM Expiration date: [never] Last password change: Сб. дек. 06 09:21:17 MSK 2014 Password expiration date: [none] Maximum ticket life: 1 day 00:00:00 Maximum renewable life: 0 days 00:00:00 Last modified: Сб. дек. 06 09:21:17 MSK 2014 (root/admin@EXAMPLE.COM) Last successful authentication: [never] Last failed authentication: [never] Failed password attempts: 0 Number of keys: 6 Key: vno 2, aes256-cts-hmac-sha1-96, no salt Key: vno 2, aes128-cts-hmac-sha1-96, no salt Key: vno 2, des3-cbc-sha1, no salt Key: vno 2, arcfour-hmac, no salt Key: vno 2, des-hmac-sha1, no salt Key: vno 2, des-cbc-md5, no salt MKey: vno 1 Attributes: Policy: [none] kadmin.local: exit
Обратите внимание, что был создан новый файл /etc/krb5.keytab. Вот почему мы запустили бинарник kadmin.local от имени суперпользователя. Иначе мы получили бы следующую ошибку:
$ kadmin.local Authenticating as principal pablo/admin@EXAMPLE.COM with password. kadmin.local: Error reading password from stash: Permission denied while initializing kadmin.local interface
Только суперпользователь имеет доступ на чтение к файлу-тайнику (/etc/krb5.d/stash.keyfile).
Давайте посмотрим, что записано в /etc/krb5.keytab:
# klist -ek /etc/krb5.keytab Keytab name: FILE:/etc/krb5.keytab KVNO Principal ---- --------------------------------------------------------------- 2 host/ldap-srv.example.com@EXAMPLE.COM (aes256-cts-hmac-sha1-96) 2 host/ldap-srv.example.com@EXAMPLE.COM (aes128-cts-hmac-sha1-96) 2 host/ldap-srv.example.com@EXAMPLE.COM (des3-cbc-sha1) 2 host/ldap-srv.example.com@EXAMPLE.COM (arcfour-hmac) 2 host/ldap-srv.example.com@EXAMPLE.COM (des-hmac-sha1) 2 host/ldap-srv.example.com@EXAMPLE.COM (des-cbc-md5)
Как мы можем видеть, это список ключей шифрования машины ldap-srv. Неудивительно, что доступ предоставлен только суперпользователю!
У нас осталась ещё одна вещь на сервере, которую надо поправить. Это ошибка
mdb_equality_candidates: (krbPrincipalName) not indexedв журнале /var/log/slapd.log. Создадим LDIF-файл 9.1-kerberos.indexes.ldif, который внесёт поправки в индексы:
dn: olcDatabase={1}mdb,cn=configchangetype: modifyadd: olcDbIndexolcDbIndex: krbPrincipalName eq-add: olcDbIndexolcDbIndex: ou eq
Добавим эти индексы в сервер каталогов:
# ldapadd -QY EXTERNAL -H ldapi:/// -f 9.1-kerberos.indexes.ldif
Отлично! Теперь у нас есть настроенный KDC!
С действующим KDC мы можем заставить клиентские машины и сервисы использовать его. Обозначим основные цели по настройке клиентов, чтобы интегрировать их в инфраструктуру Kerberos:
Где работаем: ldap-client
ВНИМАНИЕ! Клиенты Kerberos должны иметь возможность подключения к TCP портам KDC с номерами 88 и 749!
Установим необходимые пакеты:
# apt-get install krb5-user libpam-krb5 libsasl2-modules-gssapi-mit
Во время установки в качестве области Kerberos можете задать EXAMPLE.COM, а в качестве серверов, обслуживающих область, ldap-srv.example.com.
Отредактируйте конфигурацию клиента в файле /etc/krb5.conf следующим образом:
[logging]default = SYSLOG:INFO:LOCAL1kdc = SYSLOG:NOTICE:LOCAL1admin_server = SYSLOG:WARNING:LOCAL1[libdefaults]default_realm = EXAMPLE.COMdns_lookup_realm = falsedns_lookup_kdc = falseticket_lifetime = 24hrenew_lifetime = 7dforwardable = true[realms]EXAMPLE.COM = {kdc = ldap-srv.example.comadmin_server = ldap-srv.example.comdefault_domain = example.com}[domain_realm].example.com = EXAMPLE.COMexample.com = EXAMPLE.COM[appdefaults]pam = {debug = falseticket_lifetime = 36000renew_lifetime = 36000forwardable = truekrb4_convert = false}
Создайте новый принципал машины для этого хоста. Мы запускаем команду kadmin от имени суперпользователя, чтобы можно было записать результирующий файл /etc/krb5.keytab. Иначе мы получим не очень понятную ошибку No such file or directory while adding key to keytab. Мы так же должны использовать модификатор -p, чтобы дать понять команде kadmin, от имени какого принципала мы хотим подключиться. Если мы его не зададим, то получим ошибку Client not found in Kerberos database while initializing kadmin interface, потому что не создавали принципал root/admin@EXAMPLE.COM. Не создавайте этот принципал! Мы хотим знать, кто подключается с правами администратора (пользователи с префиксом /admin). Если создадим — не сможем различать администраторов между собой.
# kadmin -p pablo/admin@EXAMPLE.COM Authenticating as principal pablo/admin@EXAMPLE.COM with password. Password for pablo/admin@EXAMPLE.COM: kadmin: addprinc -randkey host/ldap-client.example.com@EXAMPLE.COM kadmin: ktadd host/ldap-client.example.com@EXAMPLE.COM kadmin: exit
Эта команда создала файл /etc/krb5.keytab.
Теперь мы можем отредактировать /etc/ssh/sshd_config и включить аутентификацию Kerberos. Не забудьте добавить test.group в директиву AllowGroups. Иначе мы не сможем протестировать конфигурацию и увидим ошибку
User test.user from ldap-srv.example.com not allowed because none of user's groups are listed in AllowGroupsв файле /var/log/auth.log.
AddressFamily inetPort 22Protocol 2AllowGroups sysadmin test.groupSyslogFacility AUTHPRIVLoginGraceTime 30sPermitRootLogin noStrictModes yesIgnoreRhosts yesPermitEmptyPasswords noPasswordAuthentication yesAllowTcpForwarding noX11Forwarding yesPrintLastLog yesClientAliveInterval 120ClientAliveCountMax 2Banner /etc/issueUsePAM yesChallengeResponseAuthentication yesKerberosAuthentication yesKerberosOrLocalPasswd yesKerberosTicketCleanup yesGSSAPIAuthentication yesGSSAPICleanupCredentials yes
Перезапустим демон:
# service ssh restart
Запустите на клиентской рабочей станции отображение файла журнала:
# tail -F /var/log/auth.log
А пока вернёмся на сервер.
Где работаем: ldap-srv
Создадим принципал пользователя test.user:
$ kadmin -p pablo/admin@EXAMPLE.COM Authenticating as principal pablo/admin@EXAMPLE.COM with password. Password for pablo/admin@EXAMPLE.COM: kadmin: addprinc test.user@EXAMPLE.COM WARNING: no policy specified for test.user@EXAMPLE.COM; defaulting to no policy Enter password for principal "test.user@EXAMPLE.COM": Re-enter password for principal "test.user@EXAMPLE.COM": Principal "test.user@EXAMPLE.COM" created. kadmin: exit
Возьмём билет Kerberos у test.user и прикинемся этим пользователем. Сначалы мы уничтожим свои собственные билеты (если они есть), используя kdestroy, затем возьмём билет test.user с помощью kinit, а в итоге проверим, что он у нас есть с помощью klist:
$ kdestroy $ kinit -p test.user@EXAMPLE.COM Password for test.user@EXAMPLE.COM: $ klist Ticket cache: FILE:/tmp/krb5cc_1000 Default principal: test.user@EXAMPLE.COM Valid starting Expires Service principal 06.12.2014 14:58:06 07.12.2014 14:58:06 krbtgt/EXAMPLE.COM@EXAMPLE.COM
Теперь попробуем авторизоваться на клиенте без пароля, используя этот билет:
$ ssh test.user@ldap-client.example.com
Где работаем: ldap-client
В открытом нами журнале на клиенте /var/log/auth.log мы должны увидеть что-то подобное:
Dec 6 15:00:55 ldap-client sshd[2170]: Authorized to test.user, krb5 principal test.user@EXAMPLE.COM (krb5_kuserok) Dec 6 15:00:55 ldap-client sshd[2170]: Accepted gssapi-with-mic for test.user from 192.168.122.150 port 45995 ssh2 Dec 6 15:00:55 ldap-client sshd[2170]: pam_unix(sshd:session): session opened for user test.user by (uid=0)
Успех! Переходим к следующей цели.
Где работаем: ldap-srv
Для настройки аутентификаци SASL GSSAPI мы должны изменить конфигурацию сервера OpenLDAP таким образом, чтобы он знал о существовании нашей области Kerberos. После этого мы можем настроить клиентов.
Подключимся к KDC и создадим новый принципал. Мы по-прежнему запускаем kadmin от имени суперпользователя, потому что хотим создать новый набор ключей в файле /etc/ldap/krb5.keytab, чтобы наш демон slapd имел свой набор.
# kadmin -p pablo/admin@EXAMPLE.COM kadmin: addprinc -randkey ldap/ldap-srv.example.com@EXAMPLE.COM kadmin: ktadd -k /etc/ldap/krb5.keytab ldap/ldap-srv.example.com@EXAMPLE.COM
Поменяем права доступа на этот файл, чтобы демон slapd смог его читать:
# chown root:openldap /etc/ldap/krb5.keytab # chmod 640 /etc/ldap/krb5.keytab
Создадим LDIF-файл 9.2.2-sasl.ldif с директивами SASL:
dn: cn=configchangetype: modifyadd: olcSaslSecPropsolcSaslSecProps: noanonymous,noplain-add: olcSaslHostolcSaslHost: ldap-srv.example.com-add: olcSaslRealmolcSaslRealm: EXAMPLE.COM
И загрузим его в базу данных службы каталогов:
# ldapadd -QY EXTERNAL -H ldapi:/// -f 9.2.2-sasl.ldif
На самом деле нам не нужно играться с olcSaslSecProps, но я оставил его, потому что пытался добавить ключевое слово noactive. Если при этом попытаться выполнить поиск, то получим следующую ошибку:
# ldapsearch -LLLY EXTERNAL -H ldapi:/// -b cn=config -s base | grep -i sasl SASL/EXTERNAL authentication started ldap_sasl_interactive_bind_s: Authentication method not supported (7) additional info: SASL(-4): no mechanism available: security flags do not match required
В данный момент такое поведение — не совсем то, что нам нужно. Может быть позже. Сейчас проверим, загрузил ли демон slapd нашу конфигурацию SASL:
# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b cn=config -s base | grep -i sasl olcSaslSecProps: noanonymous,noplain olcSaslHost: ldap-srv.example.com olcSaslRealm: EXAMPLE.COM
Хорошо! Теперь нам нужно добавить параметр KRB5_KTNAME в файл /etc/default/slapd:
SLAPD_CONF=SLAPD_USER="openldap"SLAPD_GROUP="openldap"SLAPD_PIDFILE=SLAPD_SERVICES="ldap:/// ldapi:///"SLAPD_SENTINEL_FILE=/etc/ldap/noslapdSLAPD_OPTIONS="-4"export KRB5_KTNAME=/etc/ldap/krb5.keytab
Для того, чтобы изменения вступили в силу, нам нужно перезапустить демон slapd:
# service slapd restart
Демон slapd снова запущен — мы можем переходить к настройке клиента.
Где работаем: ldap-client
Зайдём на клиентскую рабочую станцию по ssh от имени пользователя pablo:
$ ssh pablo/admin@ldap-client.example.com
Или даже так:
$ ssh pablo/admin@EXAMPLE.COM@ldap-client.example.com
Получим билет от KDC:
$ kdestroy $ kinit -p pablo/admin $ klist Ticket cache: FILE:/tmp/krb5cc_1000 Default principal: pablo@EXAMPLE.COM Valid starting Expires Service principal 07.12.2014 14:16:24 08.12.2014 14:16:24 krbtgt/EXAMPLE.COM@EXAMPLE.COM
Все настройки для доступа на сервер у нас уже внесены в файл /etc/ldap/ldap.conf. Проверим, можем ли мы сделать запрос к LDAP-серверу:
$ ldapwhoami ldap_sasl_interactive_bind_s: No such object (32)
Такая ошибка может показаться странной. Нужно указать механизм GSSAPI для доступа с помощью SASL. Такой вариант должен сработать:
$ ldapwhoami -Y GSSAPI SASL/GSSAPI authentication started SASL username: pablo@EXAMPLE.COM SASL SSF: 56 SASL data security layer installed. dn:uid=pablo,cn=example.com,cn=gssapi,cn=auth
Супер! Добавленный модификатор мы тоже можем внести в /etc/ldap/ldap.conf, чтобы его не приходилось вбивать вручную каждый раз:
BASE dc=example,dc=comURI ldap://ldap-srv.example.comTLS_CACERT /etc/ssl/certs/rootca.crtTLS_CRLFILE /etc/ssl/rootca.crlTLS_REQCERT allowTIMELIMIT 15TIMEOUT 20SASL_MECH GSSAPI
Вы заметили, что OpenLDAP преобразовал имя принципала Kerberos в формат DN (Distinguished Name)? У нас был принципал с таким именем:
pablo@EXAMPLE.COM
который был преобразован slapd в это:
dn:uid=pablo,cn=example.com,cn=gssapi,cn=auth
Это значит нам нужно вернуться на сервер и задать новые правила доступа (ACL), если мы хотим, чтобы наш Kerberos-принципал AutoFS мог читать информацию для автоматического монтирования.
Вздохните поглубже, далее от Вас потребуется внимательность и терпение. ;)
Где работаем: ldap-srv
Вернёмся на наш сервер OpenLDAP и отредактируем правила доступа ACL. Но прежде чем мы продолжим, всегда неплохо проверить текущую конфигурацию. Теперь мы можем формировать запросы с использованием GSSAPI (без модификатора -x):
$ ldapsearch -xZZLLLWD cn=admin,dc=example,dc=com -b cn=config olcAccess
Запрос вернёт нам четыре DN с атрибутами olcAccess:
dn: olcDatabase={-1}frontend,cn=config
dn: olcDatabase={0}config,cn=config
dn: olcDatabase={1}mdb,cn=config
dn: olcDatabase={2}monitor,cn=config
Мы должны изменить ACL для olcDatabase={0}config и olcDatabase={1}mdb. Приготовьтесь, ACL станут немного сложней. Создадим LDIF-файл 9.2.3-gssapi.acl.ldif и запишем в него:
dn: olcDatabase={0}config,cn=configchangetype: modifydelete: olcAccess-add: olcAccessolcAccess: {0}to *by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manageby dn.regex="uid=.*/admin,cn=example.com,cn=gssapi,cn=auth" managedn: olcDatabase={1}mdb,cn=configchangetype: modifydelete: olcAccess-add: olcAccessolcAccess: {0}to *by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manageby * break-add: olcAccess# Позволять принципалам Kerberos с префиксом /admin# менять любые пароли.olcAccess: {1}to attrs=userPassword,userPKCS12by dn.regex="uid=.*/admin,cn=example.com,cn=gssapi,cn=auth" manageby self writeby anonymous auth-add: olcAccess# Позволять принципалам Kerberos с префиксом /admin# записывать метку времени об изменении пароля.olcAccess: {2}to attrs=shadowLastChangeby dn.regex="uid=.*/admin,cn=example.com,cn=gssapi,cn=auth" manageby self write-add: olcAccess# Позволять принципалам Kerberos с префиксом /admin просматривать# контейнер с настройками Kerberos, но не менять его содержимое.# Это правило заставит пользоваться инструментами Kerberos при администрировании области.olcAccess: {3}to dn.subtree="cn=kerberos,ou=services,dc=example,dc=com"by dn.exact="cn=krbadmin,ou=users,dc=example,dc=com" writeby dn.regex="uid=.*/admin,cn=example.com,cn=gssapi,cn=auth" read-# Позволять принципалам Kerberos с именем autofsclient/*# видеть содержимое карт автоматического монтирования.add: olcAccessolcAccess: {4}to dn.subtree="ou=autofs,ou=services,dc=example,dc=com"by dn.regex="uid=.*/admin,cn=example.com,cn=gssapi,cn=auth" manageby dn.regex="uid=autofsclient/.*,cn=example.com,cn=gssapi,cn=auth" read-add: olcAccess# Позволять принципалам Kerberos с префиксом /admin доступ на запись к остальному каталогу.olcAccess: {5}to *by dn.regex="uid=.*/admin,cn=example.com,cn=gssapi,cn=auth" manageby dn.exact="cn=krbadmin,ou=users,dc=example,dc=com" writeby self readby dn.base="cn=nssproxy,ou=users,dc=example,dc=com" read
Ух! Вы поняли все производимые изменения? Напоминаю, что cn=admin,dc=example,dc=com (RootDN) всегда имеет полный доступ к olcDatabase={1}mdb,cn=config. То же касается и olcDatabase={0}config. Поэтому cn=admin явно не упомянут в ACL. Не волнуйтесь и внимательно прочитайте правила, одно за другим. У Вас всё получится ;)
Изменения масштабные, поэтому сделаем резервную копию на случай, если всё пойдёт наперекосяк:
# tar zcvf ~/ldap/slapd.d.backup.tar.gz /etc/ldap/slapd.d
Загрузим новые ACL в конфигурацию OpenLDAP:
# ldapmodify -QY EXTERNAL -H ldapi:/// -f 9.2.3-gssapi.acl.ldif
modifying entry "olcDatabase={-1}frontend,cn=config"
modifying entry "olcDatabase={0}config,cn=config"
modifying entry "olcDatabase={1}mdb,cn=config"
modifying entry "olcDatabase={2}monitor,cn=config"
Проверим, что cn=admin,dc=example,dc=com имеет права доступа к базе данных сервера OpenLDAP. Следующий запрос должен вернуть dn: cn=config:
$ ldapsearch -xLLLZWD cn=admin,dc=example,dc=com -b cn=config -s base dn
Суперпользователь с UID и GID равными нулю имеет аналогичный уровень доступа:
# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=config -s base dn
Такой же уровень доступа имеют принципалы с префиксом /admin. Получим билет принципала и выполним запрос от его имени с помощью SASL:
$ kdestroy $ kinit -p pablo/admin@EXAMPLE.COM $ ldapsearch -ZZLLLQb cn=config -s base dn dn: cn=config
Проверьте, работают ли права для пользователя cn=nssproxy. Следующая команда должна вернуть все DN из DIT кроме записей, в которых присутствует cn=kerberos:
$ ldapsearch -xZZLLLWD cn=nssproxy,ou=users,dc=example,dc=com -b dc=example,dc=com dn
А могут ли обычные пользователи менять свой пароль? Проверим это с клиентской рабочей станции.
Где работаем: ldap-client
Процесс обновления пароля изменился. Если мы попытаемся запустить команду passwd от имени пользователя, которого нет в локальном файле /etc/passwd, пароль будет изменен с использованием механизмов Kerberos:
$ su - test.user $ passwd Current Kerberos password: Новый пароль : Повторите ввод нового пароля : passwd: password updated successfully
Для спокойствия убедимся, что пароль поменялся в нужном месте. Сверим текущее время и время изменения пароля в принципале test.user@EXAMPLE.COM. Они должны различаться незначительно.
Время изменения пароля записывается в принципалах в атрибуте krbLastPwdChange. Запись содержит время по Гринвичу (GMT). Поэтому для начала посмотрим текущее время GMT на клиентской машине:
$ date -u Сб. дек. 20 17:19:24 UTC 2014
Теперь получим билет администратора, чтобы заглянуть в атрибуты принципала test.user@EXAMPLE.COM.
$ kdestroy $ kinit -p pablo/admin@EXAMPLE.COM
И наконец, отправим вот такой длиннющий запрос (ответ сервера — только последняя строчка) к серверу каталогов по атрибуту krbLastPwdChange:
$ ldapsearch -ZZLLLQb krbPrincipalName=test.user@EXAMPLE.COM,cn=EXAMPLE.COM,cn=kerberos,ou=services,dc=example,dc=com -s base krbLastPwdChange dn: krbPrincipalName=test.user@EXAMPLE.COM,cn=EXAMPLE.COM,cn=kerberos,ou=servi ces,dc=example,dc=com krbLastPwdChange: 20141220171526Z
Как мы можем видеть, пароль принципала test.user@EXAMPLE.COM был изменён четыре минуты назад (буква Z указывает на время по Гринвичу). Замечательно!
Теперь мы можем настроить клиентскую машину для использования механизма GSSAPI в работе с картами автомонтирования AutoFS. На этом этапе Вы должны быть авторизованы на клиентской машине от имени пользователя, домашний каталог которого не лежит на сервере NFS! Если это не так, авторизуйтесь повторно.
Перед тем как продолжить, проверьте, отмонтированы ли все каталоги NFS:
$ df -h
Проверьте общесистемную конфигурацию AutoFS в файле /etc/defaults/autofs:
TIMEOUT=300BROWSE_MODE="no"MOUNT_NFS_DEFAULT_PROTOCOL=4LOGGING="debug"OPTIONS="-d -v"LDAP_URI="ldap://ldap-srv.example.com"SEARCH_BASE="ou=autofs,ou=services,dc=example,dc=com"MAP_OBJECT_CLASS="automountMap"ENTRY_OBJECT_CLASS="automount"MAP_ATTRIBUTE="ou"ENTRY_ATTRIBUTE="cn"VALUE_ATTRIBUTE="automountInformation"USE_MISC_DEVICE="yes"
Заметьте, что атрибут LOGGING установлен в значение debug, а OPTIONS — в -d -v. Это для того, чтобы помочь нам с поиском проблем, если они возникнут. В рабочей конфигурации этот параметр должен быть изменён. Мы вернёмся к этому через пару минут.
Далее нам нужно создать принципал Kerberos для демона autofs. Мы так же должны добавить ключи этого нового принципала в набор ключей нашего клиента.
# kadmin -p pablo/admin@EXAMPLE.COM kadmin: addprinc -randkey autofsclient/ldap-client.example.com@EXAMPLE.COM kadmin: ktadd autofsclient/ldap-client.example.com@EXAMPLE.COM
Как мы можем видеть, ключи autofsclient теперь являются частью набора ключей клиента:
# klist -ek /etc/krb5.keytab Keytab name: FILE:/etc/krb5.keytab KVNO Principal ---- -------------------------------------------------------------------------- 2 host/ldap-client.example.com@EXAMPLE.COM (aes256-cts-hmac-sha1-96) 2 host/ldap-client.example.com@EXAMPLE.COM (aes128-cts-hmac-sha1-96) 2 host/ldap-client.example.com@EXAMPLE.COM (des3-cbc-sha1) 2 host/ldap-client.example.com@EXAMPLE.COM (arcfour-hmac) 2 host/ldap-client.example.com@EXAMPLE.COM (des-hmac-sha1) 2 host/ldap-client.example.com@EXAMPLE.COM (des-cbc-md5) 2 autofsclient/ldap-client.example.com@EXAMPLE.COM (aes256-cts-hmac-sha1-96) 2 autofsclient/ldap-client.example.com@EXAMPLE.COM (aes128-cts-hmac-sha1-96) 2 autofsclient/ldap-client.example.com@EXAMPLE.COM (des3-cbc-sha1) 2 autofsclient/ldap-client.example.com@EXAMPLE.COM (arcfour-hmac) 2 autofsclient/ldap-client.example.com@EXAMPLE.COM (des-hmac-sha1) 2 autofsclient/ldap-client.example.com@EXAMPLE.COM (des-cbc-md5)
Теперь мы можем изменить порядок аутентификации autofs в файле /etc/autofs_ldap_auth.conf, используя механизм GSSAPI и новый принципал:
<?xml version="1.0" ?><autofs_ldap_sasl_confusetls="yes"tlsrequired="yes"authrequired="yes"authtype="GSSAPI"clientprinc="autofsclient/ldap-client.example.com@EXAMPLE.COM"/><!-- EOF -->
Перезапустим демон autofs:
# service autofs restart
Проверим журнал /var/log/syslog, всё ли работает?
... Dec 20 22:12:27 ldap-client automount[943]: Starting automounter version 5.0.7, master map auto.master Dec 20 22:12:27 ldap-client automount[943]: using kernel protocol version 5.02 Dec 20 22:12:27 ldap-client automount[943]: lookup_nss_read_master: reading master ldap auto.master Dec 20 22:12:28 ldap-client kernel: [ 4.116950] e1000: eth0 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: RX Dec 20 22:12:28 ldap-client kernel: [ 4.118253] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready Dec 20 22:12:28 ldap-client nslcd[972]: version 0.8.13 starting Dec 20 22:12:28 ldap-client nslcd[972]: accepting connections Dec 20 22:12:28 ldap-client automount[943]: master_do_mount: mounting /nfs Dec 20 22:12:28 ldap-client automount[943]: automount_path_to_fifo: fifo name /var/run/autofs.fifo-nfs Dec 20 22:12:28 ldap-client automount[943]: lookup_nss_read_map: reading map ldap ldap:ou=auto.nfs,ou=autofs,ou=services,dc=example,dc=com Dec 20 22:12:28 ldap-client automount[943]: mounted indirect on /nfs with timeout 300, freq 75 seconds Dec 20 22:12:28 ldap-client automount[943]: st_ready: st_ready(): state = 0 path /nfs ...
Отлично! Попробуем перейти в каталог /nfs/home:
$ cd /nfs/home $ pwd /nfs/home
Супер! Изменим атрибуты LOGGING и OPTIONS в файле /etc/defaults/autofs на повседневные:
...
LOGGING="none"
# OPTIONS="-d -v"
...
И перезапустим демон autofs:
# service autofs restart
Вот и всё! На этом фокусы с Kerberos закончились. :)
В следующем разделе мы опишем, как создавать резервную копию сервера OpenLDAP и восстанавливаться из неё. Затем мы настроим репликацию. Принимая во внимание зависимость наших клиентов от сервера OpenLDAP, нам надо обеспечить некоторый уровень отказоустойчивости.
В этом разделе мы настроим сервер каталогов для хранения конфигурации NFS netgroup. Это механизм разграничения доступа к сетевым ресурсам. Затем мы настроим клиента NFS, чтобы проверить, что наша конфигурация netgroup действительно работает.
ВНИМАНИЕ! Прежде чем переходить к следующему разделу и добавлять группы oracle и itdept, ознакомьтесь с проблемой, описанной в разделе 8.4. Для того, чтобы она у Вас не появилась, можете прямо сейчас выполнить инструкции раздела 8.4.2 и потом вернуться сюда. А можете и не выполнять. Зависит от того, является ли это проблемой в Вашем конкретном случае.
Где работаем: ldap-srv
Нам понадобится схема наборов данных Network Information Service (NIS). В разделе 2.5 мы уже добавили её в конфигурацию сервера каталогов. Проверим, что она на месте:
$ ldapsearch -xZZLLLWD cn=admin,dc=example,dc=com -b cn=schema,cn=config dn | grep nis
Enter LDAP Password:
dn: cn={10}nis,cn=schema,cn=config
Проверим, содержит ли эта схема атрибуты для netgroup:
$ sudo ldapsearch -xZZLLLWD cn=admin,dc=example,dc=com -b cn={10}nis,cn=schema,cn=config | grep NAME | cut -d' ' -f5 | grep -i netgroup
Enter LDAP Password:
'memberNisNetgroup'
'nisNetgroupTriple'
'nisNetgroup'
Хорошо. Но у нас пока нет никаких записей, которые используют эти атрибуты. Создадим LDIF-файл 8.1-netgroup.ldif, который добавит в службу каталогов контейнер для конфигураций netgroup и несколько примеров групп netgroup:
# Контейнер для конфигураций netgroupdn: ou=netgroup,ou=services,dc=example,dc=comou: netgroupobjectClass: topobjectClass: organizationalUnitdescription: NFS Netgroups# Первый пример группы netgroupdn: cn=oracle,ou=netgroup,ou=services,dc=example,dc=comobjectClass: topobjectClass: nisNetgroupcn: oraclenisNetgroupTriple: (oracle.example.com,,)description: All Oracle machines# Второй пример группы netgroupdn: cn=itdept,ou=netgroup,ou=services,dc=example,dc=comobjectClass: topobjectClass: nisNetgroupcn: itdeptnisNetgroupTriple: (ldap-client.example.com,,)description: IT department machines
Будьте осторожны с использованием FQDN в наборах netgroup!
Если Вы сделаете это неверно, ничего не заработает. Например, такая запись ошибочна:
nisNetgroupTriple: (ldap-client.example.com,,example.com)
А такая запись — верная:
nisNetgroupTriple: (ldap-client.example.com,,)
Такой вариант записи тоже допускается:
nisNetgroupTriple: (ldap-client,,example.com)
Выберите синтаксис, который больше по душе, и придерживайтесь его.
Добавим новые записи в службу каталогов:
$ ldapadd -xZZWD cn=admin,dc=example,dc=com -f 8.1-netgroup.ldif Enter LDAP Password: adding new entry "ou=netgroup,ou=services,dc=example,dc=com" adding new entry "cn=oracle,ou=netgroup,ou=services,dc=example,dc=com" adding new entry "cn=itdept,ou=netgroup,ou=services,dc=example,dc=com"
Где работаем: nfs-srv
Наш сервер NFS уже интегрирован с сервером каталогов в соответствии с разделом 7. Нижеследующие манипуляции без этого не заработают.
Измените значение конфигурации netgroup в файле /etc/nsswitch.conf, чтобы информация о группах netgroup запрашивалась только у сервера каталогов:
netgroup: ldap
Проверим, что возвращает запрос конфигурации netgroup к нашему серверу каталогов:
$ getent netgroup Перечисление не поддерживается для netgroup
Хм, интересно. Так как netgroup, в сущности, — механизм безопасности, у нас не получится просмотреть весь их список сразу. Значит, надо проверить их по-отдельности:
$ getent netgroup oracle oracle (oracle.example.com,,) $ getent netgroup itdept itdept (ldap-client.example.com,,)
Вот так выглядит запись о событии запроса getent netgroup itdept в журнале slapd.log на сервере каталогов:
slapd[870]: conn=1448 op=2 SRCH base="dc=example,dc=com" scope=2 deref=0 filter="(&(objectClass=nisNetgroup)(cn=itdept))" slapd[870]: conn=1448 op=2 SRCH attr=cn nisNetgroupTriple memberNisNetgroup slapd[870]: conn=1448 op=2 SEARCH RESULT tag=101 err=0 nentries=1 text=
Теперь изменим файл с записями экспортируемых каталогов /etc/exports, чтобы он выглядел так:
/export/home @itdept(rw,no_subtree_check)/export/install @itdept(rw,no_subtree_check)
Обратите внимание, что мы определили нашу новую группу с помощью знака @. Клиентская машина ldap-client — часть этой группы netgroup. Поэтому она должна иметь возможность монтировать указанные каталоги. Но прежде чем мы это проверим, нужно обновить конфигурацию демона NFS:
# service nfs-kernel-server reload $ showmount -e Export list for nfs-srv.example.com: /export/install @itdept /export/home @itdept
Теперь можем протестировать наши новые группы netgroup на клиентской машине ldap-client.
Где работаем: ldap-client
Подключитесь к клиентской машине. Используйте пользователя, чей домашний каталог не находится в /nfs/home!
$ ssh pablo@ldap-client.example.com
В разделе 7 мы уже настроили эту машину в качестве клиента NFS с использованием autofs. Теперь посмотрим, можем ли мы автоматически монтировать каталог /nfs/home с новыми настройками сервера NFS. Первым делом изменим конфигурацию netgroup в /etc/nsswitch.conf, чтобы она выглядела так:
netgroup: ldap
Проверим, есть ли у нас доступ к записям netgroup на сервере каталогов:
$ getent netgroup itdept itdept (ldap-client.example.com,,)
Хорошо. Теперь удостоверимся, что /nfs/home не примонтирован. ВНИМАНИЕ! Не выполняйте нижеследующую команду от имени пользователя, домашний каталог которого находится в /nfs/home!
# umount /nfs/home
Проверим, анонсирует ли сервер NFS ресурсы, доступные для группы itdept:
$ showmount -e nfs-srv.example.com Export list for nfs-srv.example.com: /export/install @itdept /export/home @itdept
Анонсирует. Следовательно, мы должны иметь возможность примонтировать их:
$ cd /nfs/home $ df -h . Файл.система Размер Использовано Дост Использовано% Cмонтировано в nfs-srv.example.com:/export/home 3,6G 1,6G 1,8G 47% /nfs/home
Отлично! Работает. Но сработает ли автоматическое монтирование, если у нас нет доступа? Для этого понадобится отмонтировать каталоги /nfs/home и /nfs/install на клиенте:
# umount /nfs/home # umount /nfs/install
Перейдём на сервер NFS и изменим настройки доступа к сетевым ресурсам.
Где работаем: nfs-srv
Отредактируем файл /etc/exports, изменив группу netgroup:
/export/home @oracle(rw,no_subtree_check)/export/install @oracle(rw,no_subtree_check)
Мы заменили группу itdept, в которую входит машина ldap-client.example.com на группу oracle, в которую эта машина не входит. Теперь машина ldap-client.example.com не сможет получить доступ к сетевым ресурсам. Но чтобы изменения вступили в силу, нужно перезагрузить сервис NFS:
# service nfs-kernel-server reload $ showmount -e Export list for nfs-srv.example.com: /export/home @oracle
Вернёмся на клиентскую машину и попробуем получить доступ к ресурсам, анонсируемым nfs-srv. Напоминаю, надо использовать учётную запись пользователя, домашний каталог которого не лежит в /nfs/home!
Где работаем: ldap-client
Попробуем открыть каталог /nfs/home:
$ cd /nfs/home -bash: cd: /nfs/home: Нет такого файла или каталога
Отлично! Это значит, что наши группы netgroup работают.
Этот раздел справочный. Для дальнейших экспериментов он играет роль постольку-поскольку.
Где работаем: ldap-srv
Я столкнулся со следующей проблемой. При попытке добавить новое значение атрибута nisNetgroupTriple в запись cn=itdept,ou=netgroup,ou=services,dc=example,dc=com появляется ошибка. Возьмём в качестве примера вот такой LDIF файл 8.4.1-ldap-client2-netgroup.ldif:
dn: cn=itdept,ou=netgroup,ou=services,dc=example,dc=comchangetype: modifyadd: nisNetgroupTriplenisNetgroupTriple: (ldap-client2.example.com,,)
При попытке его загрузить в сервер каталогов мы увидим ошибку:
$ ldapadd -xZZWD cn=admin,dc=example,dc=com -f 8.4.1-ldap-client2-netgroup.ldif Enter LDAP Password: modifying entry "cn=itdept,ou=netgroup,ou=services,dc=example,dc=com" ldap_modify: Inappropriate matching (18) additional info: modify/add: nisNetgroupTriple: no equality matching rule
После небольших поисков, стало понятно, что это не ошибка, а ограничение схемы данных nis. Два возможных пути в такой ситуации:
ou=netgroup,ou=services,dc=example,dc=com целиком и создать её заново с новыми наборами nisNetgroupTriple.nisNetgroupTriple, вроде такого:dn: cn=itdept,ou=netgroup,ou=services,dc=example,dc=comchangetype: modifyreplace: nisNetgroupTriplenisNetgroupTriple: (ldap-client.example.com,,)nisNetgroupTriple: (ldap-client2.example.com,,)
Несмотря на то, что данные способы работают, использовать их повседневно может быть накладно. Вариант — написать какой-нибудь скрипт, автоматизирующий этот процесс, но лучше прибегнуть к ещё одному способу.
Где работаем: ldap-srv
Есть третий путь, который позволит нам добавлять/удалять наборы nisNetgroupTriple. Он требует модификации схемы данных nis. Однако тут мы вновь сталкиваемся с неудобством. Перед изменением схемы придётся удалить все записи, в которых есть атрибут nisNetgroupTriple, потому что мы собираемся изменить определение этого атрибута.
Вот diff оригинальной и модифицированной схемы с парой строк контекста (-C 1), чтобы было видно, где были произведены изменения:
# diff -C 1 cn\=\{10\}nis.ldif.original cn\=\{10\}nis.ldif.modified
*** cn={10}nis.ldif.original 2012-05-17 17:26:18.479629651 -0400
--- cn={10}nis.ldif.modified 2012-05-17 17:28:46.289627851 -0400
***************
*** 33,35 ****
olcAttributeTypes: {12}( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple' DESC 'Netgr
! oup triple' SYNTAX 1.3.6.1.1.1.0.0 )
olcAttributeTypes: {13}( 1.3.6.1.1.1.1.15 NAME 'ipServicePort' EQUALITY intege
--- 33,35 ----
olcAttributeTypes: {12}( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple' DESC 'Netgr
! oup triple' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: {13}( 1.3.6.1.1.1.1.15 NAME 'ipServicePort' EQUALITY intege
Как мы можем видеть, изменение объекта nisNetgroupTriple довольно тривиальное.
Но произвести это изменение — задача не очень тривиальная.
Для начала удалим все дочерние записи у ou=netgroup,ou=services,dc=example,dc=com:
$ ldapdelete -xZZWD cn=admin,dc=example,dc=com cn=oracle,ou=netgroup,ou=services,dc=example,dc=com $ ldapdelete -xZZWD cn=admin,dc=example,dc=com cn=itdept,ou=netgroup,ou=services,dc=example,dc=com
Посмотрим, какой порядковый номер у схемы данных nis в нашем каталоге:
$ ldapsearch -xZZLLLWD cn=admin,dc=example,dc=com -b cn=schema,cn=config dn |grep nis
Enter LDAP Password:
dn: cn={10}nis,cn=schema,cn=config
Так, номер 10. Теперь посмотрим, какой порядковый номер у атрибута nisNetgroupTriple в схеме данных nis:
$ ldapsearch -xZZLLLWD cn=admin,dc=example,dc=com -b cn=schema,cn=config | grep nisNetgroupTriple
Enter LDAP Password:
olcAttributeTypes: {12}( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple' DESC 'Netgr
a netgroup' SUP top STRUCTURAL MUST cn MAY ( nisNetgroupTriple $ memberNisNe
Номер 12. Замечательно. Сформируем новый LDIF под названием 8.4.2-nis-schema-change.ldif для изменения схемы. Если два последних номера у Вас отличаются — подставьте свои значения:
dn: cn={10}nis,cn=schema,cn=configchangetype: modifydelete: olcAttributeTypesolcAttributeTypes: {12}( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple' DESC 'Netgroup triple' SYNTAX 1.3.6.1.1.1.0.0 )-add: olcAttributeTypesolcAttributeTypes: {12}( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple' DESC 'Netgroup triple' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
Загрузим его в наш сервер каталогов:
$ ldapadd -xZZWD cn=admin,dc=example,dc=com -f nis-schema-change.ldif
И проверим результат:
$ ldapsearch -xZZLLLWD cn=admin,dc=example,dc=com -b cn={10}nis,cn=schema,cn=config olcAttributeTypes |grep -A 1 nisNetgroupTriple
Enter LDAP Password:
olcAttributeTypes: {12}( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple' DESC 'Netgr
oup triple' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
Отлично! Схема данных обновлена. Теперь можем добавлять новые записи в группы netgroup по одной без каких-либо проблем. Это особенно удобно при работе с каталогом из GUI какого-нибудь LDAP-браузера (пример — Apache Directory Studio). Если Вы пришли в этот раздел прямиком из начала раздела 8, то можете продолжить в 8.1. Если Вы уже проделывали все предыдущие пункты, то остаётся только вернуть на место группы netgroup. Следуя нашим примерам, вернуть их можно с помощью такого нехитрого файла LDIF (8.4.2-netgroup-addentryonly.ldif):
dn: cn=oracle,ou=netgroup,ou=services,dc=example,dc=comobjectClass: topobjectClass: nisNetgroupcn: oraclenisNetgroupTriple: (oracle.example.com,,)description: All Oracle machinesdn: cn=itdept,ou=netgroup,ou=services,dc=example,dc=comobjectClass: topobjectClass: nisNetgroupcn: itdeptnisNetgroupTriple: (ldap-client.example.com,,)description: IT department machines
Загрузим его в наш сервер каталогов:
$ ldapadd -xZZWD cn=admin,dc=example,dc=com -f netgroup-addentryonly.ldif
Следующий раздел опишет, как развернуть область (realm) Kerberos с использованием OpenLDAP в качестве хранилища принципалов (principal). Это будет очень весело! Потому что как только у нас есть область Kerberos, мы можем использовать её для безопасной аутентификации в ssh, для защиты соединений с OpenLDAP с помощью SASL GSSAPI, для защиты запросов NFS на автоматическое монтирование и самого доступа к сетевым ресурсам. И много для чего ещё!
В этом разделе мы разберёмся, как настроить сервер NFS. Клиент NFS (ldap-client) будет монтировать ресурсы сервера с помощью autofs версии 5. При этом карты автоматического монтирования будут располагаться на сервере OpenLDAP (ldap-srv). Мы так же создадим центральный NFS репозиторий для программного обеспечения.
Развернём NFS-сервер по аналогии с первым разделом. Для начала обновим информацию на DNS сервере (в нашем случае — в файле /etc/hosts):
Где работаем: dns-srv
127.0.0.1 localhost192.168.122.140 dns-srv.example.com192.168.122.150 ldap-srv.example.com192.168.122.151 ldap-client.example.com192.168.122.154 nfs-srv.example.com
И перезапустим демон DNS, чтобы изменения вступили в силу:
# service dnsmasq restart
Теперь настроим наш NFS-сервер.
Где работаем: nfs-srv
Настроим сеть в файле /etc/network/interfaces:
auto loiface lo inet loopbackauto eth0iface eth0 inet staticaddress 192.168.122.154netmask 255.255.255.0gateway 192.168.122.1dns-nameservers 192.168.122.140
Настроим имя NFS-сервера. В Ubuntu 14.04 останов или перезапуск сервиса networking не поддерживается, поэтому придётся сделать так:
# echo 'nfs-srv.example.com' > /etc/hostname # reboot
Проверим разрешение имени будущего сервера LDAP:
$ dig nfs-srv.example.com +short 192.168.122.150
Проверим обратное разрешение имени:
$ dig -x `dig nfs-srv.example.com +short` +short nfs-srv.example.com.
Где работаем: nfs-srv
Установим необходимые пакеты:
# passwd Введите новый пароль UNIX: Повторите ввод нового пароля UNIX: passwd: password updated successfully # apt-get install nfs-common nfs-kernel-server nfs4-acl-tools libnss-ldapd libpam-ldapd sudo-ldap
Заменим ссылку /etc/sudo-ldap.conf на пустой файл:
# rm /etc/sudo-ldap.conf # touch /etc/sudo-ldap.conf
Так как наши пользовательские учётные записи хранятся на сервере OpenLDAP, NFS-сервер тоже должен быть LDAP-клиентом. Произведём их интеграцию. Для этого надо внести изменения в четыре конфигурационных файла и произвести ряд нехитрых манипуляций.
Конфигурация LDAP-клиента в /etc/ldap/ldap.conf:
BASE dc=example,dc=comURI ldap://ldap-srv.example.comTLS_CACERT /etc/ssl/certs/rootca.crtTLS_REQCERT demandTLS_CRLFILE /etc/ssl/rootca.crlTIMELIMIT 15TIMEOUT 20
Конфигурация LDAP для sudo в /etc/sudo-ldap.conf:
BASE dc=example,dc=comURI ldap://ldap-srv.example.comTLS_CACERT /etc/ssl/certs/rootca.crtTLS_REQCERT demandTLS_CRLFILE /etc/ssl/rootca.crlBINDDN cn=nssproxy,ou=users,dc=example,dc=comBINDPW пароль.пользователя.nssproxySUDOERS_BASE ou=sudo,ou=services,dc=example,dc=comTIMELIMIT 15TIMEOUT 20
Конфигурация локальной службы имён LDAP в /etc/nslcd.conf:
uid nslcdgid nslcduri ldap://ldap-srv.example.combase dc=example,dc=combinddn cn=nssproxy,ou=users,dc=example,dc=combindpw пароль.пользователя.nssproxyrootpwmoddn cn=admin,dc=example,dc=combase group ou=groups,dc=example,dc=combase passwd ou=users,dc=example,dc=combase shadow ou=users,dc=example,dc=combind_timelimit 5timelimit 10idle_timelimit 60ssl start_tlstls_reqcert nevertls_cacertfile /etc/ssl/certs/rootca.crtnss_initgroups_ignoreusers bin,daemon,games,lp,mail,nobody,nslcd,root,sshd,sync,uucpnss_initgroups_ignoreusers sys,man,news,proxy,www-data,backup,list,irc,gnats,landscape
Конфигурация Name Service Switch (NSS) в /etc/nsswitch.conf:
passwd: compat ldapgroup: compat ldapshadow: compat ldaphosts: files dnsnetworks: filesprotocols: db filesservices: db filesethers: db filesrpc: db filesnetgroup: nis ldapsudoers: files ldap
Скопируем сертификат нашего удостоверяющего центра и CRL на NFS-сервер. Подставим вместо user имя Вашей пользовательской учётной записи на ldap-srv:
# scp user@ldap-srv.example.com:/etc/ssl/certs/rootca.crt /etc/ssl/certs/ # scp user@ldap-srv.example.com:/etc/ssl/rootca.crl /etc/ssl/
Завершая интеграцию с LDAP-сервером, поменяем права доступа к /etc/nslcd.conf и /etc/sudo-ldap.conf, потому что теперь в них хранится информация для аутентификации. Затем перезапустим сервисы nslcd и nscd:
# chmod 600 /etc/{nslcd.conf,sudo-ldap.conf}
# chown root:root /etc/sudo-ldap.conf
# chown nslcd:nslcd /etc/nslcd.conf
# service nslcd restart
* Restarting LDAP connection daemon nslcd [ OK ]
# service nscd restart
* Restarting LDAP connection daemon nscd [ OK ]
Теперь удостоверимся, что пользователя test.user нет в локальной конфигурации в /etc/passwd:
$ grep ^test.user /etc/passwd || echo No such user No such user
А теперь проверим, что мы можем получить информацию об этом пользователе от нашего сервера каталогов. Напоминаю, что данные shadow можно получить только выполнив getent от имени суперпользователя (UID=0):
$ getent passwd test.user test.user:x:1101:1101:Test User:/home/test.user:/bin/bash $ getent group test.group test.group:*:1101: # getent shadow test.user test.user:*:15140:0:99999:7:::0
Можем переходить к настройке сетевых ресурсов.
Где работаем: nfs-srv
Создайте каталоги, в которых будут находиться пользовательские домашние каталоги (/export/home) и центральный репозиторий программного обеспечения (/export/install):
# mkdir -p /export/home /export/install
Держите в уме, что нам необходим домашний каталог для каждого пользователя.
Теперь можем создать тестовый пример. Для этих целей у нас и есть учётная запись test.user:
# mkdir /export/home/test.user # cp /etc/skel/.* /export/home/test.user # chown -R test.user:test.group /export/home/test.user
Если забыли пароль учётной записи test.user, теперь можем его поменять:
$ ldappasswd -xZZWD cn=admin,dc=example,dc=com -S cn=test.user,ou=users,dc=example,dc=com
Укажем экспортируемые каталоги в /etc/exports:
/export/home *.example.com(rw,no_subtree_check) /export/install *.example.com(rw,no_subtree_check)
Перезапустим демон NFS:
# service nfs-kernel-server restart
И проверим работоспособность:
$ showmount -e Export list for nfs-srv.example.com: /export/install *.example.com /export/home *.example.com
Каталоги успешно экспортируются. С помощью сервера OpenLDAP мы будем централизованно управлять тем, что и куда монтировать на клиентских машинах.
Где работаем: ldap-srv
Теперь, когда сервер NFS настроен, мы должны добавить новую схему данных для автоматического монтирования в базу данных нашего сервера каталогов. Самый простой способ её получить — установить пакет autofs-ldap:
# apt-get install autofs-ldap
Искомая схема данных - /etc/ldap/schema/autofs.schema. Как Вы уже возможно догадались, прежде всего её надо перевести в формат LDIF. В разделе 2.5 для этого мы использовали скрипт 2.5-schema-ldif.sh. Схема autofs.schema зависит от схемы core.schema. Поэтому перед конвертацией надо добавить в итоговый autofs.schema директиву include. Выполним в консоли:
$ echo "include /etc/ldap/schema/core.schema" > ~/ldap/autofs.schema $ cat /etc/ldap/schema/autofs.schema >> ~/ldap/autofs.schema $ SCHEMAS='autofs.schema' ~/ldap/2.5-schema-ldif.sh config file testing succeeded
Посмотрим содержимое получившегося LDIF. Он довольно короткий:
$ cat ~/ldap/autofs.ldif
dn: cn=autofs,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: autofs
olcAttributeTypes: {0}( 1.3.6.1.1.1.1.25 NAME 'automountInformation' DESC 'Inf
ormation used by the autofs automounter' EQUALITY caseExactIA5Match SYNTAX 1.
3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
olcObjectClasses: {0}( 1.3.6.1.1.1.1.13 NAME 'automount' DESC 'An entry in an
automounter map' SUP top STRUCTURAL MUST ( cn $ automountInformation $ object
class ) MAY description )
olcObjectClasses: {1}( 1.3.6.1.4.1.2312.4.2.2 NAME 'automountMap' DESC 'An gro
up of related automount objects' SUP top STRUCTURAL MUST ou )
Пeреместим его к остальным наборам схем:
# mv autofs.ldif /etc/ldap/schema
Загрузим его в конфигурацию сервера каталогов:
$ ldapadd -xZZWD cn=admin,dc=example,dc=com -f /etc/ldap/schema/autofs.ldif Enter LDAP Password: adding new entry "cn=autofs,cn=schema,cn=config"
Можем удостовериться в том, что схема данных загружена:
$ ldapsearch -xZZLLLWD cn=admin,dc=example,dc=com -b cn=schema,cn=config dn | grep auto
Enter LDAP Password:
dn: cn={14}autofs,cn=schema,cn=config
Создадим файл конфигурации с картами автоматического монтирования (7.4-autofs-map.ldif):
# Контейнер для конфигураций autofsdn: ou=autofs,ou=services,dc=example,dc=comou: AutoFSobjectClass: topobjectClass: organizationalUnitdescription: Automount maps# Контейнер для карты auto.masterdn: ou=auto.master,ou=autofs,ou=services,dc=example,dc=comou: auto.masterobjectClass: topobjectClass: automountMap# Точка монтирования /nfsdn: cn=/nfs,ou=auto.master,ou=autofs,ou=services,dc=example,dc=comcn: /nfsobjectClass: topobjectClass: automountautomountInformation: ldap:ou=auto.nfs,ou=autofs,ou=services,dc=example,dc=com rsize=8192,wsize=8192# Контейнер для карты auto.nfsdn: ou=auto.nfs,ou=autofs,ou=services,dc=example,dc=comou: auto.nfsobjectClass: topobjectClass: automountMap# Конфигурация дочерней точки монтирования home карты auto.nfsdn: cn=home,ou=auto.nfs,ou=autofs,ou=services,dc=example,dc=comobjectClass: topobjectClass: automountcn: homeautomountInformation: nfs-srv.example.com:/export/home# Конфигурация дочерней точки монтирования install карты auto.nfsdn: cn=install,ou=auto.nfs,ou=autofs,ou=services,dc=example,dc=comobjectClass: topobjectClass: automountcn: installautomountInformation: nfs-srv.example.com:/export/install
И добавим новую информацию в службу каталогов:
$ ldapadd -xZZWD cn=admin,dc=example,dc=com -f 7.4-autofs-map.ldif
Проверить сделанные изменения можно так:
$ ldapsearch -xZZLLLWD cn=admin,dc=example,dc=com -b ou=autofs,ou=services,dc=example,dc=com dn Enter LDAP Password: dn: ou=autofs,ou=services,dc=example,dc=com dn: ou=auto.master,ou=autofs,ou=services,dc=example,dc=com dn: cn=/nfs,ou=auto.master,ou=autofs,ou=services,dc=example,dc=com dn: ou=auto.nfs,ou=autofs,ou=services,dc=example,dc=com dn: cn=home,ou=auto.nfs,ou=autofs,ou=services,dc=example,dc=com dn: cn=install,ou=auto.nfs,ou=autofs,ou=services,dc=example,dc=com
Отлично! Теперь мы готовы настроить клиент для сервера NFS.
Где работаем: ldap-client
В предыдущих разделах мы уже произвели интеграцию клиента с сервером каталогов. В этом разделе настроим на нём демон автоматического монтирования так, чтобы демон брал карты монтирования с сервера каталогов.
Как всегда, для начала установим несколько пакетов:
# apt-get install nfs-common nfs4-acl-tools autofs5 autofs5-ldap
Настроим демон, транслирующий UID/GID в имена и наоборот (rpc.idmapd) в файле /etc/idmapd.conf:
[General]Verbosity = 0Pipefs-Directory = /run/rpc_pipefsDomain = example.com[Mapping]Nobody-User = nobodyNobody-Group = nogroup[Translation]Method = nsswitchGSS-Methods = nsswitch
Добавим в /etc/nsswitch.conf строку:
automount: ldap
Настроим демон автоматического монтирования в файле /etc/default/autofs:
TIMEOUT=300BROWSE_MODE="no"MOUNT_NFS_DEFAULT_PROTOCOL=4# Измените LOGGING на "none", если собираетесь использовать конфигурацию в продакшенеLOGGING="debug"LDAP_URI="ldap://ldap-srv.example.com"SEARCH_BASE="ou=autofs,ou=services,dc=example,dc=com"MAP_OBJECT_CLASS="automountMap"ENTRY_OBJECT_CLASS="automount"MAP_ATTRIBUTE="ou"ENTRY_ATTRIBUTE="cn"VALUE_ATTRIBUTE="automountInformation"USE_MISC_DEVICE="yes"
Настроим аутентификацию демона автоматического монтирования в файле /etc/autofs_ldap_auth.conf:
<?xml version="1.0" ?><autofs_ldap_sasl_confusetls="yes"tlsrequired="no"authrequired="simple"user="cn=nssproxy,ou=users,dc=example,dc=com"secret="пароль.пользователя.nssproxy"/><!-- EOF -->
Снова прячем файл с аутентификационной информацией от посторонних глаз, иначе демон автоматического монтирования его не примет:
# chmod 0600 /etc/autofs_ldap_auth.conf # chown root:root /etc/autofs_ldap_auth.conf
Убедимся, что rpcbind стартует при загрузке системы и перезапустим его. То же самое сделаем с демоном autofs. Для корректной работы rpcbind лично мне пришлось перезагрузить клиентскую рабочую станцию. Вывод убран для краткости:
# update-rc.d rpcbind defaults # service rpcbind restart # update-rc.d autofs defaults # service autofs restart
Проверьте файлы журналов сервера (nfs-srv) и клиента (ldap-client). Если всё в порядке, можно проверять созданную нами конфигурацию на клиентской машине:
$ ls -a /nfs/ . .. $ cd /nfs/home $ pwd /nfs/home $ cd /nfs/install $ pwd /nfs/install $ ls -a /nfs . .. home install $ df -h /nfs/home Файл.система Размер Использовано Дост Использовано% Cмонтировано в nfs-srv.example.com:/export/home 3,6G 1,6G 1,8G 47% /nfs/home $ df -h /nfs/install Файл.система Размер Использовано Дост Использовано% Cмонтировано в nfs-srv.example.com:/export/install 3,6G 1,6G 1,8G 47% /nfs/install
Если Вы видите похожий вывод, то цель достигнута!
Для организации репликации нашего DIT понадобится развернуть второй сервер OpenLDAP. Новую виртуальную машину назовём ldap-srv-repl. В соответствии с терминологией Syncrepl, мы будем работать со следующими сущностями:
Первая задача — прочитать раздел о репликации в руководстве администратора OpenLDAP. Отдельный интерес представляет следующий отрывок:
Syncrepl поддерживает синхронизацию как на основе запросов, так и на основе посылок. В его базовом режиме синхронизацииrefreshOnly(только обновление), поставщик использует синхронизацию на основе запросов, не требующей отслеживания серверов-потребителей и хранения истории операций. Информация, которая нужна поставщику для обработки периодических запросов на проверку содержимого каталога, находится в синхронизационных куки самих запросов. Для оптимизации синхронизации на основе запросов, Syncrepl использует фазу наличия (present phase) и фазу удаления (delete phase) протокола LDAP Sync, вместо того, чтобы возвращаться к частым полным перезагрузкам содержимого каталога. Для дальнейшей оптимизации синхронизации на основе запросов поставщик может вести журнал в рамках сессии в качестве хранилища истории операций. В режиме синхронизацииrefreshAndPersist(обновление и непрерывность) поставщик использует синхронизацию на основе посылок. Поставщик отслеживает серверы-потребители, запросившие непрерывно-действующий поиск, и посылает им необходимые обновления по мере изменения реплицируемого содержимого каталога поставщика.
Репликация реализуется через наложения OpenLDAP. Ознакомьтесь с инструкцией slapo-syncprov в документации man. В ней представлена информация о наложении поставщика репликации. С её помощью мы настроим репликацию в режиме refreshAndPersist с использованием схемы дельта-syncrepl. Обратите внимание, что говорит официальная документация:
Как видите, в использовании Syncrepl и slapd-ldap(8) Вы можете позволить разгуляться своему воображению, адаптируя технологии репликации к своей конкретной сетевой топологии.
Настройка дельта-syncrepl предполагает работу и с поставщиком (мастер-сервер), и с потребителем (сервер-реплика). Для начала займёмся поставщиком. У нас это ldap-srv.example.com.
План действий по настройке поставщика:
cn=accesslog);dc=example,dc=com);Где работаем: ldap-srv
Чтобы подключить динамические модули для наложений accesslog и syncprov не помешает проверить, как подключены уже имеющиеся модули. Мы делали это в разделе 2.4. Воспользуемся настроенным Kerberos и механизмом аутентификации SASL GSSAPI, чтобы упростить наши запросы. Заметьте, что Вы всегда можете использовать учётную запись RootDN (cn=admin,dc=example,dc=com), но это будет длиннее.
$ cd ~/ldap
$ kdestroy
$ kinit -p pablo/admin
$ ldapsearch -ZZQLLLb cn=config dn |grep module
dn: cn=module{0},cn=config
Как мы видим, информация о подключенных модулях содержится в записи cn=module{0},cn=config. Посмотрим, какие атрибуты в ней есть:
$ ldapsearch -ZZQLLLb cn=module{0},cn=config
dn: cn=module{0},cn=config
objectClass: olcModuleList
cn: module{0}
olcModulePath: /usr/lib/ldap
olcModuleLoad: {0}back_mdb.la
olcModuleLoad: {1}back_monitor.la
Два динамических модуля у нас уже подключены. Лежат ли в одном каталоге с ними искомые модули наложений?
$ ls /usr/lib/ldap/ |egrep '(accesslog.la|syncprov.la)' accesslog.la syncprov.la
Вот этот короткий LDIF-файл 11.1.1-new-modules.ldif поможет нам их подключить:
dn: cn=module{0},cn=configchangetype: modifyadd: olcModuleLoadolcModuleLoad: {2}accesslog.la-add: olcModuleLoadolcModuleLoad: {3}syncprov.la
Загружаем LDIF:
$ ldapmodify -ZZQf 11.1.1-new-modules.ldif
Проверяем результат:
$ ldapsearch -ZZQLLLb cn=module{0},cn=config
dn: cn=module{0},cn=config
objectClass: olcModuleList
cn: module{0}
olcModulePath: /usr/lib/ldap
olcModuleLoad: {0}back_mdb.la
olcModuleLoad: {1}back_monitor.la
olcModuleLoad: {2}accesslog.la
olcModuleLoad: {3}syncprov.la
Где работаем: ldap-srv
После подключения динамического модуля наложения accesslog мы должны создать базу данных для хранения журнала доступа. Очевидно, мы можем сделать это с помощью ещё одного LDIF-файла (11.1.2-accesslog.ldif):
dn: olcDatabase=mdb,cn=configchangetype: addobjectClass: olcDatabaseConfigobjectClass: olcMdbConfigolcDatabase: mdbolcDbDirectory: /var/lib/ldap/accesslogolcSuffix: cn=accesslogolcRootDN: cn=admin,dc=example,dc=comolcDbIndex: default eqolcDbIndex: entryCSN,objectClass,reqEnd,reqResult,reqStart
Создадим каталог для этой базы данных:
# mkdir -p /var/lib/ldap/accesslog # chown -R openldap:openldap /var/lib/ldap
И загрузим конфигурацию LDIF в наш сервер каталогов:
$ ldapadd -ZZQf 11.1.2-accesslog.ldif adding new entry "olcDatabase=mdb,cn=config"
Посмотрим, какой порядковый номер у новой базы данных:
$ ldapsearch -ZZQLLLb cn=config dn |grep mdb
dn: olcDatabase={1}mdb,cn=config
dn: olcDatabase={3}mdb,cn=config
Первая строка вывода — наше основное DIT. Значит вторая — только что добавленная запись. Проверим только что загруженую конфигурацию:
$ ldapsearch -ZZQLLLb olcDatabase={3}mdb,cn=config
Где работаем: ldap-srv
Определим наложение syncprov для новой базы данных с помощью LDIF-файла 11.1.3-overlay.accesslog.ldif:
dn: olcOverlay=syncprov,olcDatabase={3}mdb,cn=configchangetype: addobjectClass: olcOverlayConfigobjectClass: olcSyncProvConfigolcOverlay: syncprovolcSpNoPresent: TRUEolcSpReloadHint: TRUE
Так как мы будем использовать репликацию на основе журнала доступа, отключаем использование фазы наличия с помощью атрибута olcSpNoPresent. Атрибут olcSpReloadHint указывает, что наложение должно соблюдать флаг reloadHint в Sync Control. Этот флаг используется потребителем, запрашивающим операцию репликации, для указания того, что он хочет принудительно выполнить загрузку полного DIT независимо от всех остальных параметров и значений, таких как Sync Cookie.
Загрузим конфигурацию:
$ ldapadd -ZZQf 11.1.3-overlay.accesslog.ldif
adding new entry "olcOverlay=syncprov,olcDatabase={3}mdb,cn=config"
В базе данных olcDatabase={3}mdb,cn=config должна появиться новая DN-запись:
$ ldapsearch -ZZQLLLb olcDatabase={3}mdb,cn=config
dn: olcDatabase={3}mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: {3}mdb
olcDbDirectory: /var/lib/ldap/accesslog
olcSuffix: cn=accesslog
olcRootDN: cn=admin,dc=example,dc=com
olcDbIndex: default eq
olcDbIndex: entryCSN,objectClass,reqEnd,reqResult,reqStart
dn: olcOverlay={0}syncprov,olcDatabase={3}mdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: {0}syncprov
olcSpNoPresent: TRUE
olcSpReloadHint: TRUE
Где работаем: ldap-srv
Новый LDIF-файл 11.1.4-overlay.primary.ldif преследует три цели:
Запишем в 11.1.4-overlay.primary.ldif:
dn: olcDatabase={1}mdb,cn=configchangetype: modifyadd: olcDbIndexolcDbIndex: entryCSN eq-add: olcDbIndexolcDbIndex: entryUUID eq# Добавить наложение syncprov поверх базы данных dc=example,dc=com.dn: olcOverlay=syncprov,olcDatabase={1}mdb,cn=configobjectClass: olcOverlayConfigobjectClass: olcSyncProvConfigolcOverlay: syncprovolcSpCheckPoint: 500 15# Добавить наложение accesslog поверх базы данных dc=example,dc=com.# Ежедневно сканировать журнал доступа к базе данных и очищать записи старше 7 дней.dn: olcOverlay=accesslog,olcDatabase={1}mdb,cn=configobjectClass: olcOverlayConfigobjectClass: olcAccessLogConfigolcOverlay: accesslogolcAccessLogDB: cn=accesslogolcAccessLogOps: writesolcAccessLogPurge: 7+00:00 1+00:00olcAccessLogSuccess: TRUE
Загрузим конфигурацию:
$ ldapadd -ZZQf 11.1.4-overlay.primary.ldif
modifying entry "olcDatabase={1}mdb,cn=config"
adding new entry "olcOverlay=syncprov,olcDatabase={1}mdb,cn=config"
adding new entry "olcOverlay=accesslog,olcDatabase={1}mdb,cn=config"
Убедимся, что новые наложения на месте:
$ ldapsearch -ZZQLLLb olcDatabase={1}mdb,cn=config dn
dn: olcDatabase={1}mdb,cn=config
dn: olcOverlay={0}syncprov,olcDatabase={1}mdb,cn=config
dn: olcOverlay={1}accesslog,olcDatabase={1}mdb,cn=config
Где работаем: ldap-srv
Для функций репликации нам нужна новая учётная запись пользователя. Она будет использоваться для аутентификации и выгрузки данных сервером-репликой. Ни больше, ни меньше. Очередной LDIF-файл 11.1.5-replication.ldif поможет нам добавить эту запись:
dn: cn=replication,dc=example,dc=comobjectClass: simpleSecurityObjectobjectClass: organizationalRolecn: replicationdescription: OpenLDAP Replication UseruserPassword: {SSHA}6yudY3jO+yyTyvov9LhIl1j9S9RZt7Dx
Напоминаю, следующая команда генерирует посоленый хэш вводимого пароля. Замените в вышеприведённом файле значение атрибута userPassword на результат её работы:
$ slappasswd -h '{SSHA}'
Загрузим конфигурацию:
$ ldapadd -ZZQf 11.1.5-replication.ldif adding new entry "cn=replication,dc=example,dc=com"
Обратите внимание, в нашем примере пользователь для репликации называется просто replication. Если Вы планируете иметь несколько серверов для репликации, то в идеальном случае нужно создать отдельного пользователя с уникальным именем для каждого из них. Благодаря этому Вы сможете отслеживать, какой сервер и когда производил репликацию. Вы так же можете задать, какая часть DIT будет реплицироваться каждой машиной, но это уже другая история.
Где работаем: ldap-srv
Осталось только задать новому пользователю ограничения и прописать для него ACL. Проделаем это в два шага, начиная с ограничений. Создадим LDIF-файл 11.1.6-limits.ldif и запишем в него:
# Добавить ограничения для базы данных cn=accesslogdn: olcDatabase={3}mdb,cn=configchangetype: modifyadd: olcLimitsolcLimits: dn.exact="cn=replication,dc=example,dc=com" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited-add: olcAccessolcAccess: to *by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth readby dn.regex="uid=.*/admin,cn=example.com,cn=gssapi,cn=auth" readby dn.exact="cn=admin,dc=example,dc=com" readby dn.exact="cn=replication,dc=example,dc=com" read# Добавить ограничения для базы данных dc=example,dc=comdn: olcDatabase={1}mdb,cn=configchangetype: modifyadd: olcLimitsolcLimits: dn.exact="cn=replication,dc=example,dc=com" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited
Загрузим конфигурацию:
$ ldapadd -ZZQf 11.1.6-limits.ldif
modifying entry "olcDatabase={3}mdb,cn=config"
modifying entry "olcDatabase={1}mdb,cn=config"
Следующий шаг — предоставить новому пользователю доступ на чтение в основной базе данных. Очень хорошая идея — дважды проверить текущие ACL перед подобной операцией:
$ ldapsearch -ZZQLLLb cn=config olcAccess
Теперь можем создать ещё один LDIF-файл, который обновит наши ACL. Здесь идея в том, чтобы иметь одинаковый набор ACL как у поставщика, так и у потребителя. За исключением того, что у потребителя нам не нужны ACL для пользователя replication (который будет описан далее в атрибуте olcSyncRepl). Сейчас же мы должны просто добавить его в ACL с номером 0. Запишем в LDIF-файл 11.1.6-provider.acl.ldif:
dn: olcDatabase={1}mdb,cn=configchangetype: modifydelete: olcAccessolcAccess: {0}-add: olcAccessolcAccess: {0}to *by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manageby dn.exact="cn=replication,dc=example,dc=com" readby * break
Загрузим изменение ACL:
$ ldapadd -ZZQf 11.1.6-provider.acl.ldif
modifying entry "olcDatabase={1}mdb,cn=config"
Так мы можем проверить результат:
$ ldapsearch -ZZQLLLb olcDatabase={1}mdb,cn=config olcAccess
Нам надо убедиться, что пользователь cn=replication,dc=example,dc=com имеет доступ ко всему DIT:
$ ldapsearch -xZZLLLWD cn=replication,dc=example,dc=com -H ldap://ldap-srv.example.com
Наличие доступа ко всему DIT — обязательно. Не идите дальше, пока этого не добъётесь. Когда всё получилось, мы можем перейти к настройке сервера-реплики (потребителя).
Развернём новый сервер по аналогии с разделом 1.
Где работаем: dns-srv
Для начала обновим информацию на DNS сервере (файл /etc/hosts):
127.0.0.1 localhost192.168.122.140 dns-srv.example.com192.168.122.150 ldap-srv.example.com192.168.122.151 ldap-client.example.com192.168.122.154 nfs-srv.example.com192.168.122.160 ldap-srv-repl.example.com
Теперь установим Ubuntu 14.04 server на наш сервер-реплику и перейдём к его настройке.
Где работаем: ldap-srv-repl
Настроим сеть в файле /etc/network/interfaces:
auto loiface lo inet loopbackauto eth0iface eth0 inet staticaddress 192.168.122.160netmask 255.255.255.0gateway 192.168.122.1dns-nameservers 192.168.122.140
Настроим имя сервера-реплики. В Ubuntu 14.04 останов или перезапуск сервиса networking не поддерживается, поэтому придётся сделать так:
# echo 'ldap-srv-repl.example.com' > /etc/hostname # reboot
Проверим разрешение имени будущего сервера-реплики LDAP:
$ dig ldap-srv-repl.example.com +short 192.168.122.160
Проверим обратное разрешение имени:
$ dig -x `dig ldap-srv-repl.example.com +short` +short ldap-srv-repl.example.com.
Убедитесь, что время на ldap-srv и ldap-srv-repl совпадает. Часы всех наших серверов должны быть синхронизированы с использованием NTP, атомных часов или любого другого источника.
Где работаем: ldap-srv-repl
Зададим пароль для суперпользователя и установим необходимые пакеты:
# passwd # apt-get install -y slapd ldap-utils krb5-kdc-ldap krb5-pkinit wamerican libsasl2-modules-gssapi-mit
Теперь мы должны настроить сервер OpenLDAP с пустой базой данных. Подробно этот процесс описан в разделе 2. Но некоторые детали будут различаться, поэтому нельзя дословно повторять его здесь. Тезисно пробежим по основным моментам.
Создадим временный каталог для работы со службой каталогов:
$ mkdir ~/ldap $ cd ~/ldap
Подготовим каталоги для конфигурации и базы данных демона slapd:
# service slapd stop # rm -rf /etc/ldap/slapd.d # rm -rf /var/lib/ldap # mkdir /etc/ldap/slapd.d # mkdir /var/lib/ldap # chown openldap:openldap /var/lib/ldap # chmod 0700 /var/lib/ldap
Утянем с сервера ldap-srv схемы наборов данных в формате LDIF (мы их готовили самостоятельно):
# scp user@ldap-srv.example.com:/etc/ldap/schema/{autofs,sudo,kerberos}.ldif /etc/ldap/schema
Подготовим посоленый хэш пароля для администратора OpenLDAP на текущем сервере:
$ slappasswd -h '{SSHA}'
New password:
Re-enter new password:
{SSHA}AUEv75PLvTDOyrO5yYvQXmyRurYwTdmn
Теперь у нас есть всё, чтобы написать конфигурацию сервера в LDIF-формате. Для понимания синтаксиса Syncrepl ознакомьтесь с документацией. Запишем в файл 11.2.2-consumer.slapd.ldif:
dn: cn=configobjectClass: olcGlobalcn: configolcPidFile: /var/run/slapd/slapd.pidolcArgsFile: /var/run/slapd/slapd.argsdn: olcDatabase={0}config,cn=configobjectClass: olcDatabaseConfigolcDatabase: {0}configolcRootDN: cn=configolcAccess: to *by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manageby * nonedn: cn=schema,cn=configobjectClass: olcSchemaConfigcn: schemadn: cn=module,cn=configobjectClass: olcModuleListcn: moduleolcModulePath: /usr/lib/ldapolcModuleLoad: back_mdb.laolcModuleLoad: back_monitor.lainclude: file:///etc/ldap/schema/core.ldifinclude: file:///etc/ldap/schema/cosine.ldifinclude: file:///etc/ldap/schema/inetorgperson.ldifinclude: file:///etc/ldap/schema/collective.ldifinclude: file:///etc/ldap/schema/corba.ldifinclude: file:///etc/ldap/schema/duaconf.ldifinclude: file:///etc/ldap/schema/openldap.ldifinclude: file:///etc/ldap/schema/dyngroup.ldifinclude: file:///etc/ldap/schema/java.ldifinclude: file:///etc/ldap/schema/misc.ldifinclude: file:///etc/ldap/schema/nis.ldifinclude: file:///etc/ldap/schema/ppolicy.ldifinclude: file:///etc/ldap/schema/kerberos.ldifinclude: file:///etc/ldap/schema/sudo.ldifinclude: file:///etc/ldap/schema/autofs.ldif# Основная база данныхdn: olcDatabase=mdb,cn=configobjectClass: olcMdbConfigolcDatabase: mdbolcSuffix: dc=example,dc=comolcDbDirectory: /var/lib/ldapolcDbMaxsize: 1073741824olcRootDN: cn=admin,dc=example,dc=comolcRootPW: {SSHA}AUEv75PLvTDOyrO5yYvQXmyRurYwTdmn# Специальные индексы для SyncreplolcDbIndex: entryUUID eq# Директивы SyncreplolcSyncRepl: rid=0provider=ldap://ldap-srv.example.com:389bindmethod=simplestarttls=yesbinddn="cn=replication,dc=example,dc=com"credentials="пароль.пользователя.replication"searchbase="dc=example,dc=com"logbase="cn=accesslog"logfilter="(&(objectClass=auditWriteObject)(reqResult=0))"schemachecking=ontype=refreshAndPersistretry="60 +"syncdata=accesslog# Ссылка на мастер-сервер (поставщик)olcUpdateRef: ldap://ldap-srv.example.com# Правила доступа практически идентичны# (нет записи для пользователя replication)olcAccess: {0}to *by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manageby * breakolcAccess: {1}to attrs=userPassword,userPKCS12by dn.regex="uid=.*/admin,cn=example.com,cn=gssapi,cn=auth" manageby self writeby anonymous autholcAccess: {2}to attrs=shadowLastChangeby dn.regex="uid=.*/admin,cn=example.com,cn=gssapi,cn=auth" manageby self writeolcAccess: {3}to dn.subtree="cn=kerberos,ou=services,dc=example,dc=com"by dn.exact="cn=krbadmin,ou=users,dc=example,dc=com" writeby dn.regex="uid=.*/admin,cn=example.com,cn=gssapi,cn=auth" readolcAccess: {4}to dn.subtree="ou=autofs,ou=services,dc=example,dc=com"by dn.regex="uid=.*/admin,cn=example.com,cn=gssapi,cn=auth" manageby dn.regex="uid=autofsclient/.*,cn=example.com,cn=gssapi,cn=auth" readolcAccess: {5}to *by dn.regex="uid=.*/admin,cn=example.com,cn=gssapi,cn=auth" manageby dn.exact="cn=krbadmin,ou=users,dc=example,dc=com" writeby self readby dn.base="cn=nssproxy,ou=users,dc=example,dc=com" readdn: olcDatabase=monitor,cn=configobjectClass: olcDatabaseConfigolcDatabase: monitor
Атрибут olcUpdateRef играет очень важную роль. Вы можете настроить клиентские машины для использования сервера-реплики в качестве поставщика информации из каталога. Но эта информация будет доступна только для чтения. Если клиентская машина (или пользователь) выполнит запрос, требующий изменения записи, его запрос будет перенаправлен на основной сервер (ldap-srv.example.com).
Сгенерируем первичную конфигурацию:
# slapadd -n 0 -F /etc/ldap/slapd.d -l 11.2.2-consumer.slapd.ldif _#################### 100.00% eta none elapsed none fast! Closing DB...
Проверим корректность конфигурации:
# slaptest -uF /etc/ldap/slapd.d config file testing succeeded
Поправим права доступа к файлам конфигурации:
# chown -R openldap:openldap /etc/ldap/slapd.d
Подготовим систему журналирования. В конфигурации /etc/rsyslog.conf добавим несколько строк:
$ModLoad imuxsock # provides support for local system logging $ModLoad imklog # provides kernel logging support $KLogPermitNonKernelFacility on $ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat $RepeatedMsgReduction on $FileOwner syslog $FileGroup adm $FileCreateMode 0640 $DirCreateMode 0755 $Umask 0022 $PrivDropToUser syslog $PrivDropToGroup syslog $WorkDirectory /var/spool/rsyslog $IncludeConfig /etc/rsyslog.d/*.conf # Send slapd logs to /var/log/slapd.log if $programname == 'slapd' then /var/log/slapd.log & ~ if $programname == 'krb5kdc' then /var/log/krb5kdc.log & ~
Создадим файлы для журналов наших демонов и зададим для них права доступа. Затем перезапустим rsyslog, чтобы изменения вступили в силу:
# touch /var/log/{slapd,krb5kdc}.log
# chmod 0640 /var/log/{slapd,krb5kdc}.log
# chown syslog:adm /var/log/{slapd,krb5kdc}.log
# service rsyslog restart
Настроим logrotate для управления этими журналами.
Создадим файл конфигурации /etc/logrotate.d/slapd и запишем в него:
/var/log/slapd.log {dailymissingokrotate 7compressdelaycompressnotifempty}
Файл /etc/logrotate.d/krb5kdc для демона krb5-kdc:
/var/log/krb5kdc.log {dailymissingokrotate 7compressdelaycompressnotifempty}
Проверим настройку logrotate:
# logrotate -df /etc/logrotate.conf
Отредактируем общесистемную конфигурацию демона slapd в файле /etc/default/slapd:
SLAPD_CONF=SLAPD_USER="openldap"SLAPD_GROUP="openldap"SLAPD_PIDFILE=SLAPD_SERVICES="ldap:/// ldapi:///"SLAPD_SENTINEL_FILE=/etc/ldap/noslapdSLAPD_OPTIONS="-4"
Первичная загрузка позволяет загрузить DIT на сервер-реплику через файл, не прибегая к репликации и без формирования большого потока траффика в сети. Это не обязательно, но если DIT достаточно большое, мы можем сэкономить много времени.
Но у Вас ничего не получится, если версия используемого сервера OpenLDAP — 2.4.31 и более ранняя. Связано такое поведение с ошибкой ITS#7255, исправленной в версии 2.4.32.
Проверить версию можно так:
$ dpkg --status slapd|grep Version Version: 2.4.31-1+nmu2ubuntu8
Самый благоразумный вариант при развёртывании OpenLDAP в такой ситуации — не предпринимать ничего и просто пропустить этот раздел. Пусть пакет slapd спокойно обновится и данный функционал у Вас заработает. А первичную загрузку DIT можно произвести просто запустив механизм репликации по сети. Но в любом случае с информацией ознакомиться стоит. Она описывает более подробно процесс, тезисно зафиксированный в документации.
Где работаем: ldap-srv
Последний этап пред тем, как мы запустим репликацию — выгрузить всё DIT от поставщика потребителю.
Выгрузим всё DIT в LDIF-файл. В целях безопасности сначала зададим umask:
# umask 066 # slapcat | tee -a /tmp/provider.slapcat.ldif
Где работаем: ldap-srv-repl
Создадим каталог-приёмник для этого файла:
$ mkdir ~/dit $ chmod u=rwx,g=,o= ~/dit
Где работаем: ldap-srv
Отправим файл на сервер-реплику (если уж DIT совсем большое, вместо scp можно использовать съёмный носитель). Затем — удалим исходный файл:
# scp /tmp/provider.slapcat.ldif user@ldap-srv-repl.example.com:~/dit # shred /tmp/provider.slapcat.ldif
Где работаем: ldap-srv-repl
Уничтожим каталог с базой данных и воссоздадим его пустым:
# service slapd stop # rm -rf /var/lib/ldap # mkdir /var/lib/ldap # chmod u=rwx,g=,o= /var/lib/ldap # chown openldap:openldap /var/lib/ldap
Загрузим DIT из скопированного нами файла в базу данных поставщика. Обратите внимание на модификатор -w у команды slapadd. Он позволит записать в базу данных информацию о контексте Syncrepl. Как только все записи будут загружены, значение contextCSN обновится в соответствии с самым большим entryCSN. В нашем случае это очень кстати :)
# slapadd -l provider.slapcat.ldif -w
(именно здесь возникает проблема при использовании slapd версии 2.4.31, процесс загрузки просто зависает)
И снова уничтожим временный файл, теперь уже на клиентской машине. В конце концов, в этом файле содежится всё DIT открытым текстом:
$ shred ~/dit/provider.slapcat.ldif
Убедимся, что всё DIT находится на сервере-реплике:
$ ldapsearch -xWD cn=admin,dc=example,dc=com -b dc=example,dc=com -H ldap://ldap-srv-repl.example.com
Где работаем: ldap-srv-repl
Запускаем демон slapd и добавляем его в автозагрузку:
# service slapd start # update-rc.d slapd defaults
Слегка изменим права доступа с помощью LDIF-файла 11.2.4-consumer.acl.ldif:
dn: olcDatabase={0}config,cn=configchangetype: modifyreplace: olcRootDNolcRootDN: cn=admin,dc=example,dc=com-replace: olcAccessolcAccess: to *by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manageby dn.regex="uid=.*/admin,cn=example.com,cn=gssapi,cn=auth" manageby * none
Загрузим изменение ACL:
# ldapmodify -QY EXTERNAL -H ldapi:/// -f 11.2.4-consumer.acl.ldif
modifying entry "olcDatabase={0}config,cn=config"
Настроим общесистемную конфигурацию клиентских запросов в файле /etc/ldap/ldap.conf. Это немного сократит количество печатаемого нами текста. Пока не обращайте внимание на параметры TLS, мы разберёмся с ними в следующем разделе. Не забудьте, что в этом разделе мы работаем с ldap-srv-repl.example.com и запросы мы отправляем именно ему. Это важно, потому что мы хотим опрашивать и модифицировать только потребителя, не поставщика (ldap-srv.example.com). Итак, запишем в /etc/ldap/ldap.conf:
BASE dc=example,dc=comURI ldap://ldap-srv-repl.example.com# TLS_CACERT /etc/ssl/certs/rootca.crt# TLS_CRLFILE /etc/ssl/rootca.crl# TLS_REQCERT demandTIMELIMIT 15TIMEOUT 20
Проверим, может ли наш администратор выполнить запрос:
$ ldapwhoami -WD cn=admin,dc=example,dc=com Enter LDAP Password: dn:cn=admin,dc=example,dc=com
Если в соответствии с разделом 8.4.2 мы меняли схему данных nis, то нам придётся это повторить и здесь. Три простых шага и всё готово:
Посмотрим, какой порядковый номер у схемы данных nis в нашем каталоге и у атрибута nisNetgroupTriple в схеме данных nis:
$ ldapsearch -LLLxWD cn=admin,dc=example,dc=com -b cn=schema,cn=config dn |grep nis
Enter LDAP Password:
dn: cn={10}nis,cn=schema,cn=config
$ ldapsearch -LLLxWD cn=admin,dc=example,dc=com -b cn=schema,cn=config | grep nisNetgroupTriple
Enter LDAP Password:
olcAttributeTypes: {12}( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple' DESC 'Netgr
a netgroup' SUP top STRUCTURAL MUST cn MAY ( nisNetgroupTriple $ memberNisNe
Номера 10 и 12 соответственно. Сформируем новый LDIF под названием 11.2.4-nis-schema-change.ldif для изменения схемы. Если два последних номера у Вас отличаются — подставьте свои значения:
dn: cn={10}nis,cn=schema,cn=configchangetype: modifydelete: olcAttributeTypesolcAttributeTypes: {12}( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple' DESC 'Netgroup triple' SYNTAX 1.3.6.1.1.1.0.0 )-add: olcAttributeTypesolcAttributeTypes: {12}( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple' DESC 'Netgroup triple' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
Загрузим его в наш сервер каталогов:
$ ldapadd -xZWD cn=admin,dc=example,dc=com -f 11.2.4-consumer.nis-change.ldif
Enter LDAP Password:
modifying entry "cn={10}nis,cn=schema,cn=config"
Дважды проверьте по журналам, что Вы подключаетесь именно к серверу-реплике!
Где работаем: ldap-srv
Создадим закрытый ключ для сервера-реплики:
# cd /root/CA # openssl genrsa -out private/ldap-srv-repl.example.com.key 4096 # chmod 400 private/ldap-srv-repl.example.com.key
Сгенерируем запрос на подпись сертификата:
# openssl req -sha256 -new \
-key private/ldap-srv-repl.example.com.key -out certs/ldap-srv-repl.example.com.csr \
-subj /C=RU/ST=Moscow/L=Moscow/O=ExampleInc/OU=ITdept/CN=ldap-srv-repl.example.com/emailAddress=support@example.com
Подпишем его с помощью своего CA:
# openssl ca -extensions usr_cert -notext -md sha256 \ -keyfile private/rootca.key -cert certs/rootca.crt \ -in certs/ldap-srv-repl.example.com.csr -out certs/ldap-srv-repl.example.com.crt # chmod 444 certs/ldap-srv-repl.example.com.crt
Теперь нужно безопасным образом переместить на сервер ldap-srv-repl четыре файла:
Где работаем: ldap-srv-repl
Подготовим каталог для временного хранения этой информации на сервере-реплике в домашнем каталоге пользователя, которого Вы создали при установке операционной системы (допустим, user):
$ whoami user $ mkdir ~/certs $ chmod u=rwx,g=,o= ~/certs
Где работаем: ldap-srv
Скопируем файлы в этот каталог с сервера, где находится наш CA, используя учётную запись user:
# pwd /root/CA # scp private/ldap-srv-repl.example.com.key certs/ldap-srv-repl.example.com.crt certs/rootca.crt crl/rootca.crl user@ldap-srv-repl.example.com:~/certs
Где работаем: ldap-srv-repl
Создадим каталог для ключевой информации нашего сервера и поместим туда получившиеся у нас файлы:
# mkdir /etc/ldap/ssl # chown openldap:openldap /etc/ldap/ssl # chmod 0500 /etc/ldap/ssl # cd /home/user/certs # mv ldap-srv-repl.example.com.crt ldap-srv-repl.example.com.key /etc/ldap/ssl
Установим права доступа для ключевой информации:
# chown openldap:openldap /etc/ldap/ssl/{ldap-srv-repl.example.com.crt,ldap-srv-repl.example.com.key}
# chmod 0400 /etc/ldap/ssl/{ldap-srv-repl.example.com.crt,ldap-srv-repl.example.com.key}
Поместим корневой сертификат и список отозванных сертификатов в каталог с сертификатами операционной системы и зададим для них права доступа:
# mv rootca.crt /etc/ssl/certs/ # chmod 0644 /etc/ssl/certs/rootca.crt # mv rootca.crl /etc/ssl/ # chmod 0644 /etc/ssl/rootca.crl
Опишем конфигурацию TLS для ldap-srv-repl в LDIF-файле 11.2.5-tls.consumer.ldif:
dn: cn=configadd: olcTLSCertificateFileolcTLSCertificateFile: /etc/ldap/ssl/ldap-srv-repl.example.com.crt-add: olcTLSCertificateKeyFileolcTLSCertificateKeyFile: /etc/ldap/ssl/ldap-srv-repl.example.com.key-add: olcTLSCACertificateFileolcTLSCACertificateFile: /etc/ssl/certs/rootca.crt-add: olcTLSVerifyClientolcTLSVerifyClient: never
Загрузим конфигурацию:
$ ldapmodify -xWD cn=admin,dc=example,dc=com -f 11.2.5-tls.consumer.ldif
И проверим результат:
# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b cn=config -s base | grep olcTLS olcTLSCertificateFile: /etc/ldap/ssl/ldap-srv-repl.example.com.crt olcTLSCertificateKeyFile: /etc/ldap/ssl/ldap-srv-repl.example.com.key olcTLSCACertificateFile: /etc/ssl/certs/rootca.crt olcTLSVerifyClient: never
Раскомментируем строчки в /etc/ldap/ldap.conf:
BASE dc=example,dc=comURI ldap://ldap-srv-repl.example.comTLS_CACERT /etc/ssl/certs/rootca.crtTLS_CRLFILE /etc/ssl/rootca.crlTLS_REQCERT demandTIMELIMIT 15TIMEOUT 20
И попробуем выполнить запрос с использованием TLS (параметр -Z):
$ ldapwhoami -xZZWD cn=admin,dc=example,dc=com Enter LDAP Password: dn:cn=admin,dc=example,dc=com
С помощью LDIF-файла 11.2.5-consumer.dbindexes.ldif изменим настройки журналирования сервера каталогов и добавим индексы для основной базы данных:
dn: cn=configchangetype: modifyreplace: olcLogLevelolcLogLevel: statsdn: olcDatabase={1}mdb,cn=configchangetype: modifyadd: olcDbIndexolcDbIndex: entryCSN eq-add: olcDbIndexolcDbIndex: uid eq-add: olcDbIndexolcDbIndex: cn eq-add: olcDbIndexolcDbIndex: ou eq-add: olcDbIndexolcDbIndex: dc eq
Теперь журнал сервера будет достаточно подробным. Это поможет нам в отладке. Загрузим конфигурацию:
$ ldapadd -xZZWD cn=admin,dc=example,dc=com -f 11.2.5-consumer.dbindexes.ldif
Проверим, что у нас получилось в итоге следующей командой:
# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b cn=config "(|(cn=config)(olcDatabase={1}mdb))"
Где работаем: ldap-srv-repl
Включим аутентификацию SASL GSSAPI на новом сервере каталогов с помощью LDIF-файла 11.2.6-consumer.gssapi.ldif:
dn: cn=configchangetype: modifyadd: olcSaslHostolcSaslHost: ldap-srv-repl.example.com-add: olcSaslRealmolcSaslRealm: EXAMPLE.COM-add: olcSaslSecPropsolcSaslSecProps: noanonymous,noplain
Загрузим конфигурацию:
$ ldapadd -xZZWD cn=admin,dc=example,dc=com -f 11.2.6-consumer.gssapi.ldif
Теперь нам нужно добавить параметр KRB5_KTNAME в файл /etc/default/slapd:
SLAPD_CONF=SLAPD_USER="openldap"SLAPD_GROUP="openldap"SLAPD_PIDFILE=SLAPD_SERVICES="ldap:/// ldapi:///"SLAPD_SENTINEL_FILE=/etc/ldap/noslapdSLAPD_OPTIONS="-4"export KRB5_KTNAME=/etc/ldap/krb5.keytab
Скопириуем конфигурацию-описание области EXAMPLE.COM с основного сервера, чтобы не было проблем при подключении с помощью устилиты kadmin:
# scp user@ldap-srv.example.com:/etc/krb5.conf /etc/
Создадим набор ключей Kerberos для сервера OpenLDAP, ключ принципала сервера ldap-srv-repl и ключ autofsclient для автоматического монтирования на этом сервере в диалоге команды kadmin. ВНИМАНИЕ: заметьте, как мы размещаем принципалы в наборах ключей. Принципалы host/ и autofsclient/ размещаются в /etc/krb5.keytab, а принципал ldap/ — в /etc/ldap/krb5.keytab:
# kadmin -p pablo/admin@EXAMPLE.COM kadmin: addprinc -randkey ldap/ldap-srv-repl.example.com@EXAMPLE.COM kadmin: ktadd -k /etc/ldap/krb5.keytab ldap/ldap-srv-repl.example.com@EXAMPLE.COM kadmin: addprinc -randkey host/ldap-srv-repl.example.com@EXAMPLE.COM kadmin: ktadd -k /etc/krb5.keytab host/ldap-srv-repl.example.com@EXAMPLE.COM kadmin: addprinc -randkey autofsclient/ldap-srv-repl.example.com@EXAMPLE.COM kadmin: ktadd -k /etc/krb5.keytab autofsclient/ldap-srv-repl.example.com@EXAMPLE.COM kadmin: exit
Поправим права доступа на новый набор ключей:
# chown root:openldap /etc/ldap/krb5.keytab # chmod 640 /etc/ldap/krb5.keytab
Перезапустим демон службы каталогов:
# service slapd restart
Проверим аутентификацию SASL GSSAPI:
$ kdestroy $ kinit -p pablo/admin@EXAMPLE.COM $ ldapwhoami SASL/GSSAPI authentication started SASL username: pablo/admin@EXAMPLE.COM SASL SSF: 56 SASL data security layer installed. dn:uid=pablo/admin,cn=example.com,cn=gssapi,cn=auth
Сервер-реплика ldap-srv-repl.example.com (потребитель OpenLDAP), настроен с использованием TLS и SASL GSSAPI. Сервер получает данные от поставщика ldap-srv.example.com. Проверим, работает ли процедура репликации. В качестве примера будем менять рабочую оболочку (loginShell) пользователя test.user.
Где работаем: ldap-srv
Посмотрим текущее значение атрибута loginShell пользователя test.user:
$ ldapsearch -QLLLZZb cn=test.user,ou=users,dc=example,dc=com loginShell dn: cn=test.user,ou=users,dc=example,dc=com loginShell: /bin/bash
Где работаем: ldap-srv-repl
Проверим значение того же поля на сервере-реплике:
$ ldapsearch -QLLLZb cn=test.user,ou=users,dc=example,dc=com loginShell dn: cn=test.user,ou=users,dc=example,dc=com loginShell: /bin/bash
Где работаем: ldap-srv
Поменяем оболочку пользователя на /bin/sh:
$ ldapmodify <<-EOF dn: cn=test.user,ou=users,dc=example,dc=com changetype: modify replace: loginShell loginShell: /bin/sh EOF
Где работаем: ldap-srv-repl
Проверим, применились ли изменения на сервере-реплике:
$ ldapsearch -QLLLZb cn=test.user,ou=users,dc=example,dc=com loginShell dn: cn=test.user,ou=users,dc=example,dc=com loginShell: /bin/sh
Репликация работает! Ура!
Смысл репликации DIT — иметь запасную копию на случай выхода из строя основного сервера (поставщика). Но наше DIT помимо прочего поддерживает инфраструктуру Kerberos. Поэтому мы должны настроить сервер-реплику так, чтобы он выполнял роль подчинённого сервера Kerberos на случай выхода из строя основного.
Для развёртывания подчинённого сервера Kerberos мы уже установили необходимые пакеты и произвели некоторые настройки (в предыдущих разделах). Сейчас нам нужно переместить на подчинённый сервер три файла: закрытый ключ Kerberos, конфигурацию области и файл-тайник.
Где работаем: ldap-srv-repl
Создадим на сервере-реплике каталог для их временного хранения:
$ mkdir ~/kerberos $ chmod u=rwx,g=,o= ~/kerberos/ $ cd ~/kerberos/
Где работаем: ldap-srv
Скопируем файлы во временный каталог:
# scp /etc/krb5kdc/{.k5.EXAMPLE.COM,kdc.conf,kadm5.acl} /etc/krb5.d/stash.keyfile user@ldap-srv-repl.example.com:~/kerberos
Где работаем: ldap-srv-repl
Поместим эти файлы на свои места и поправим права доступа:
# mkdir /etc/krb5.d/
# chmod u=rwx,g=,o= /etc/krb5.d/
# mv {.k5.EXAMPLE.COM,kdc.conf,kadm5.acl} /etc/krb5kdc/
# mv stash.keyfile /etc/krb5.d/
# chown -R root:root /etc/krb5kdc /etc/krb5.d
Добавим в базу данных некоторые индексы. Запишем в файл 11.2.8-kerberos.indexes.ldif:
dn: olcDatabase={1}mdb,cn=configchangetype: modifyadd: olcDbIndexolcDbIndex: objectClass eq-add: olcDbIndexolcDbIndex: krbPrincipalName eq-add: olcDbIndexolcDbIndex: sudoUser eq,sub-add: olcDbIndexolcDbIndex: uidNumber,gidNumber,memberUid,uniqueMember eq
Загрузим конфигурацию:
$ ldapadd -QZZf 11.2.6-kerberos.indexes.ldif
Проверим, на месте ли новые индексы:
$ ldapsearch -QZZLLLb olcDatabase={1}mdb,cn=config olcDbIndex
dn: olcDatabase={1}mdb,cn=config
olcDbIndex: entryUUID eq
olcDbIndex: entryCSN eq
olcDbIndex: uid eq
olcDbIndex: cn eq
olcDbIndex: ou eq
olcDbIndex: dc eq
olcDbIndex: objectClass eq
olcDbIndex: krbPrincipalName eq
olcDbIndex: sudoUser eq,sub
olcDbIndex: uidNumber,gidNumber,memberUid,uniqueMember eq
Убедитесь, что подчинённый KDC стартует автоматически и запустите его. Обратите внимание, что демон управления доменом Kerberos (kadmind) на подчинённом сервере мы не запускаем!
# update-rc.d krb5-kdc defaults # service krb5-kdc start
Настройте резервное копирование и восстановление на сервере-реплике в соответствии с методикой, приведённой в разделе 10.
Порой файлы журналов не дают чёткого представления, закончен процесс репликации или нет. Чтобы в этом удостовериться, просто запросите у поставщика и потребителя значение contextCSN. Если ответы от обоих серверов совпадают, репликация закончена.
Где работаем: ldap-srv
$ kdestroy $ kinit -p pablo/admin $ ldapsearch -ZZQLLL -s base contextCSN dn: dc=example,dc=com contextCSN: 20150112110636.224261Z#000000#000#000000
Где работаем: ldap-srv-repl
$ kdestroy $ kinit -p pablo/admin $ ldapsearch -ZZQLLL -s base contextCSN dn: dc=example,dc=com contextCSN: 20150112110636.224261Z#000000#000#000000
Всё отлично.
Где работаем: ldap-client
Когда второй сервер OpenLDAP заработал, нам остаётся настроить клиентов, чтобы они использовали оба. Для этого отредактируем несколько файлов.
Конфигурация sudoers через LDAP (/etc/sudo-ldap.conf):
BASE dc=example,dc=comURI ldap://ldap-srv.example.com ldap://ldap-srv-repl.example.comBINDDN cn=nssproxy,ou=users,dc=example,dc=comBINDPW пароль.пользователя.nssproxyTLS_CACERTFILE /etc/ssl/certs/rootca.crtTLS_CRLFILE /etc/ssl/rootca.crlTLS_CHECKPEER noTIMELIMIT 15TIMEOUT 20SUDOERS_BASE ou=sudo,ou=services,dc=example,dc=com
Клиентская конфигурация LDAP (/etc/ldap/ldap.conf):
BASE dc=example,dc=comURI ldap://ldap-srv.example.com ldap://ldap-srv-repl.example.comTLS_CACERT /etc/ssl/certs/rootca.crtTLS_CRLFILE /etc/ssl/rootca.crlTLS_REQCERT demandTIMELIMIT 15TIMEOUT 20SASL_MECH GSSAPI
Конфигурация локальной службы имён (/etc/nslcd.conf):
uid nslcdgid nslcduri ldap://ldap-srv.example.comuri ldap://ldap-srv-repl.example.combase dc=example,dc=combinddn cn=nssproxy,ou=users,dc=example,dc=combindpw nssproxyuserpassrootpwmoddn cn=admin,dc=example,dc=combase group ou=groups,dc=example,dc=combase passwd ou=users,dc=example,dc=combase shadow ou=users,dc=example,dc=combind_timelimit 5timelimit 10idle_timelimit 60ssl start_tlstls_reqcert demandtls_cacertfile /etc/ssl/certs/rootca.crtnss_initgroups_ignoreusers bin,daemon,games,lp,mail,nobody,nslcd,root,sshd,sync,uucpnss_initgroups_ignoreusers sys,man,news,proxy,www-data,backup,list,irc,gnats,landscape
Конфигурация Kerberos (/etc/krb5.conf):
[logging]default = SYSLOG:INFO:LOCAL1kdc = SYSLOG:NOTICE:LOCAL1admin_server = SYSLOG:WARNING:LOCAL1[libdefaults]default_realm = EXAMPLE.COMdns_lookup_realm = falsedns_lookup_kdc = falseticket_lifetime = 24hrenew_lifetime = 7dforwardable = true[realms]EXAMPLE.COM = {kdc = ldap-srv.example.comkdc = ldap-srv-repl.example.comadmin_server = ldap-srv.example.commaster_kdc = ldap-srv.example.comdefault_domain = example.comdatabase_module = openldap_ldapconf}[domain_realm].example.com = EXAMPLE.COMexample.com = EXAMPLE.COM[appdefaults]pam = {debug = falseticket_lifetime = 36000renew_lifetime = 36000forwardable = truekrb4_convert = false}
Как можно видеть, изменения требуются совсем небольшие. Поэтому, возможно, Вы захотите такой процесс автоматизировать. Сделать это можно разными путями. От простой раздачи файлов по сети с помощью ftp/http/nfs до развесистой системы управления версиями вроде Puppet.
После внесения всех изменений на клиентской машине, попробуйте выключить ldap-srv.example.com и проверить, будут ли доступны сервисы, которые он поддерживал, с нового сервера ldap-srv-repl.example.com.
Если Вы испытываете трудности с Syncrepl, попробуйте настроить журналирование:
ldapmodify -Z <<-EOF dn: cn=config changetype: modify replace: olcLogLevel olcLogLevel: stats sync EOF
Вы можете сделать это как на поставщике, так и на потребителе.
Если в журнале slapd.log Вы видите подобную запись:
syncrepl_message_to_entry: rid=000 mods check (objectClass: value #1 invalid per syntax)то это значит, что на сервере-реплике нет необходимой схемы набора данных. Конечно, значение
rid=000 может быть другим на Вашем сервере. Это идентификатор репликации, задаваемый в атрибуте olcSyncrepl на севере-реплике. Сравните набор загруженных схем с основным сервером (поставщиком). Они должны совпадать. Выявите, каких схем не хватает, выполнив на каждом сервере запрос:
$ ldapsearch -ZZQLLLb cn=schema,cn=config dn
Где работаем: ldap-srv-repl
Загрузите недостающие схемы на сервер-реплику, пользуясь таким шаблоном (с использованием Kerberos):
$ ldapadd -ZZQf schema.ldif
За дополнительной информацией обратитесь к разделу 2.5.
Для начала хорошей идеей будет ознакомиться с этими источниками:
Хорошая статья на русском в вики Archlinux про sudo
Где работаем: ldap-srv
Для удобства создадим новый каталог:
$ mkdir ~/sudo $ cd ~/sudo
За основу возьмём вот такой вполне обычный файл с правилами sudo и сохраним его как 6.1-sudoers.source:
Defaults env_resetDefaults mail_badpassDefaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"root ALL=(ALL) ALL%sysadmin ALL=(ALL) ALL
Для конвертации этого файла в LDIF воспользуемся скриптом /usr/share/doc/sudo-ldap/sudoers2ldif.gz из пакета sudo-ldap:
$ zcat /usr/share/doc/sudo-ldap/sudoers2ldif.gz > 6.1-sudoers2ldif $ SUDOERS_BASE=ou=sudo,ou=services,dc=example,dc=com perl 6.1-sudoers2ldif 6.1-sudoers.source > 6.1-sudoers.ldif
Между прочим, можно и не создавать отдельный файл 6.1-sudoers.source, а просто в последней команде вместо него указать Ваш текущий /etc/sudoers. Таким образом Вы преобразуете в LDIF свою любимую конфигурацию. :)
Итак, у нас теперь есть sudoers в формате LDIF. Но в нашей службе каталогов нет контейнера для правил sudo! У нас, в сущности, даже нет контейнера для служб. Поэтому добавим в начало получившегося у нас 6.1-sudoers.ldif несколько строк для контейнера служб (первый блок строк) и входящего в него контейнера правил sudo (второй блок строк). Итоговый файл 6.1-sudoers.ldif для 6.1-sudoers.source будет выглядеть так:
dn: ou=services,dc=example,dc=comou: ServicesobjectClass: topobjectClass: organizationalUnitdescription: Group all services under this OUdn: ou=sudo,ou=services,dc=example,dc=comobjectClass: organizationalUnitdescription: sudoobjectClass: topdn: cn=defaults,ou=sudo,ou=services,dc=example,dc=comobjectClass: topobjectClass: sudoRolecn: defaultsdescription: Default sudoOption's go heresudoOption: env_resetsudoOption: mail_badpasssudoOption: secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binsudoOrder: 1dn: cn=root,ou=sudo,ou=services,dc=example,dc=comobjectClass: topobjectClass: sudoRolecn: rootsudoUser: rootsudoHost: ALLsudoRunAsUser: ALLsudoCommand: ALLsudoOrder: 2dn: cn=%sysadmin,ou=sudo,ou=services,dc=example,dc=comobjectClass: topobjectClass: sudoRolecn: %sysadminsudoUser: %sysadminsudoHost: ALLsudoRunAsUser: ALLsudoCommand: ALLsudoOrder: 3
Заметьте, директива secure_path определена без использования кавычек!
Небольшое примечание по поводу скрипта sudoers2ldif. Если в Вашем sudoers файле встречаются строки вида
env_keep = COLORSто после всех проведённых с файлом sudoers.ldif манипуляций надо сделать ещё один фокус — убрать лишние пробелы. Так, чтобы получилось
env_keep=COLORSИначе при загрузке LDIF мы получим ошибки. Провернуть это можно с помощью одной команды:
$ sed -i.bak -e "s/ = /=/g" -re 's/= {0,2}"/=/g' -e 's/"$//g' -e "s/p \+/p+/g" 6.1-sudoers.ldif
Загрузим нашу конфигурацию в каталог:
$ ldapmodify -axZZWD cn=admin,dc=example,dc=com -f 6.1-sudoers.ldif Enter LDAP Password: adding new entry "ou=services,dc=example,dc=com" adding new entry "ou=sudo,ou=services,dc=example,dc=com" adding new entry "cn=defaults,ou=sudo,ou=services,dc=example,dc=com" adding new entry "cn=root,ou=sudo,ou=services,dc=example,dc=com" adding new entry "cn=%sysadmin,ou=sudo,ou=services,dc=example,dc=com"
Убедимся, что обычные пользователи не могут просмотреть конфигурацию sudoers:
$ ldapsearch -xZZLLLWD cn=pablo,ou=users,dc=example,dc=com -b ou=sudo,ou=services,dc=example,dc=com Enter LDAP Password: No such object (32)
А вот наш пользователь nssproxy, напротив, должен иметь к ней доступ:
$ ldapsearch -xZZLLLWD cn=nssproxy,ou=users,dc=example,dc=com -b ou=sudo,ou=services,dc=example,dc=com Enter LDAP Password: dn: ou=sudo,ou=services,dc=example,dc=com objectClass: organizationalUnit ...
Вы должны были увидеть вывод, почти идентичный содержимому файла 6.1-sudoers.ldif. Если так, то продолжаем.
Где работаем: ldap-client
Теперь, когда у нас есть работающая схема sudo (dn: cn={13}sudo,cn=schema,cn=config) и LDAP-версия файла sudoers, мы можем настроить клиентские машины для запроса данных sudoers с сервера OpenLDAP.
Прежде чем установить пакет sudo-ldap необходимо задать пароль для учетной записи root:
# passwd Введите новый пароль UNIX: Повторите ввод нового пароля UNIX:
Установим sudo-ldap:
# apt-get install sudo-ldap
Конфигурация LDAP для sudo по-умолчанию считывается из ссылки /etc/sudo-ldap.conf на /etc/ldap/ldap.conf. Нам это будет не очень удобно, потому что в эту конфигурацию надо снова поместить пароль nssproxy. Поэтому удалим эту символическую ссылку и заменим её на файл с таким же именем:
# rm /etc/sudo-ldap.conf # touch /etc/sudo-ldap.conf
Запишем в файл /etc/sudo-ldap.conf:
BASE dc=example,dc=comURI ldap://ldap-srv.example.comBINDDN cn=nssproxy,ou=users,dc=example,dc=comBINDPW пароль.пользователя.nssproxyTLS_CACERTFILE /etc/ssl/certs/rootca.crtTLS_CRLFILE /etc/ssl/rootca.crlTLS_CHECKPEER noTIMELIMIT 15TIMEOUT 20SUDOERS_BASE ou=sudo,ou=services,dc=example,dc=com#SUDOERS_DEBUG 2
Настроим права доступа на этот файл (в нём теперь есть пароль!):
# chmod 600 /etc/sudo-ldap.conf # chown root:root /etc/sudo-ldap.conf
Файл сертификата нашего корневого удостоверяющего центра (rootca.crt) мы уже скопировали на ldap-client в разделе 5.
Убедимся, что в файле /etc/nsswitch.conf директива sudoers выглядит так или добавим её:
sudoers: files ldap
Проверим работоспособность наших настроек:
$ sudo -l -U pablo Matching Defaults entries for pablo on ldap-client: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, env_reset, mail_badpass, secure_path=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin User pablo may run the following commands on ldap-client: (ALL) ALL
Мы видим как локальные настройки /etc/sudoers, так и информацию из нашего каталога OpenLDAP. Значит всё работает!
Где работаем: ldap-srv
Если мы вновь заглянем в журнал /var/log/slapd.log, то увидим там ошибки такого вида:
ldap-srv slapd[868]: <= mdb_equality_candidates: (sudoUser) not indexed
Для того, чтобы это исправить сделаем вот такой небольшой LDIF-файл 6.2-sudoers.indexes.ldif с новыми индексами:
dn: olcDatabase={1}mdb,cn=configchangetype: modifyadd: olcDbIndexolcDbIndex: sudoUser eq,sub-add: olcDbIndexolcDbIndex: sudoHost eq
И загрузим его в каталог:
$ ldapmodify -axZZWD cn=admin,dc=example,dc=com -f 6.2-sudoers.indexes.ldif
Enter LDAP Password:
modifying entry "olcDatabase={1}mdb,cn=config"
Теперь при выполнении на ldap-client команд с sudo ошибок в журнале сервера быть не должно. На этом реализация хранилища настроек sudo закончена.
В наши дни использование TLS является практически обязательным. TLS реализует защитные функции конфиденциальности и целостности данных, а так же служит для поддержки аутентификации LDAP с использованием механизма SASL EXTERNAL. TLS определён в RFC4346.
Для настройки TLS на сервере нам понадобятся SSL сертификат и ключ. Сертификат должен быть подписан доверенным удостоверяющим центром (УЦ, Certificate Authority, CA) или собственным удостоверяющим центром (на основе самоподписанного, self-signed, сертификата), если используется в тестовых целях.
С помощью OpenSSL мы создадим импровизированный удостоверяющий центр и затем настроим TLS.
Прямая цитата из Википедии:
Сертификаты, как правило, используются для обмена зашифрованными данными в больших сетях. Криптосистема с открытым ключом решает проблему обмена секретными ключами между участниками безопасного обмена, однако не решает проблему доверия к открытым ключам. Предположим, что Алиса, желая получать зашифрованные сообщения, генерирует пару ключей, один из которых (открытый) она публикует каким-либо образом. Любой, кто желает отправить ей конфиденциальное сообщение, имеет возможность зашифровать его этим ключом, и быть уверенным, что только она (так как только она обладает соответствующим секретным ключом) сможет это сообщение прочесть. Однако описанная схема ничем не может помешать злоумышленнику Давиду создать пару ключей, и опубликовать свой открытый ключ, выдав его за ключ Алисы. В таком случае Давид сможет расшифровывать и читать, по крайней мере, ту часть сообщений, предназначенных Алисе, которые были по ошибке зашифрованы его открытым ключом.
Идея сертификата — это наличие третьей стороны, которой доверяют две другие стороны информационного обмена. Предполагается, что таких третьих сторон немного, и их открытые ключи всем известны каким-либо способом, например, хранятся в операционной системе или публикуются в журналах. Таким образом, подлог открытого ключа третьей стороны легко выявляется.
Если Алиса сформирует сертификат со своим публичным ключом, и этот сертификат будет подписан третьей стороной (например, Трентом), любой, доверяющий Тренту, сможет удостовериться в подлинности открытого ключа Алисы. В централизованной инфраструктуре в роли Трента выступает удостоверяющий центр. В сетях доверия Трент может быть любым пользователем, и следует ли доверять этому пользователю, удостоверившему ключ Алисы, решает сам отправитель сообщения.
Где работаем: ldap-srv
Итак, мы создаём централизованную инфраструктуру открытых ключей (PKI) в миниатюре. Для этого сформируем пару закрытый ключ/корневой сертификат удостоверяющего центра. Причём сертификат будет подписан этим же закрытым ключом (т. е. станет самоподписанным).
Затем сгенерируем новый закрытый ключ для нашей службы каталогов и создадим для неё сертификат, подписанный закрытым ключом нашего удостоверяющего центра. При этом клиенские рабочие станции должны знать только корневой сертификат. Используя его они могут установить безопасное соединение с любым сервером, который имеет закрытый ключ и соответствующий ему сертификат, подписанный нашим УЦ.
Такие пары (ключ/сертификат) можно создавать для множества задач. Например, в разделе, посвященном репликации, мы создадим второй сервер каталогов, которому тоже понадобится такая пара.
Удостоверяющий центр желательно разворачивать на отдельной машине, не имеющей подключения к сети, но для простоты примера мы проделаем всю работу на ldap-srv.example.com.
Создадим каталог для нашего удостоверяющего центра (CA) и установим безопасные права доступа. Затем зададим значение umask таким, чтобы вновь создаваемые файлы имели права доступа чтения и записи только для создавшего их пользователя:
# mkdir /root/CA # chmod u=rwx,g=,o= /root/CA # cd /root/CA # umask 066
В конфигурационном файле /etc/ssl/openssl.cnf в секции [ CA_default ] для удобства поменяем значение директивы dir = ./demoCA на dir = ./. В этом же разделе директивой default_days задаётся срок действия выпускаемых сертификатов. Можете поменять её значение по своему усмотрению.
Файлы index.txt и serial будут играть роль своеобразной базы данных, чтобы отслеживать статус выпущенных закрытых ключей и сертификатов.
Создадим структуру каталогов и файлов для своего удостоверяющего центра:
# mkdir certs crl newcerts private # chmod 700 private # touch index.txt # echo 1000 > serial
Сгенерируем закрытый ключ удостоверяющего центра (длиной 4096 бит). Он должен хранится особенно бережно. Поэтому мы защитим его при помощи шифра AES. Вам будет предложено ввести пароль для доступа к новому закрытому ключу. Запомните его и не потеряйте. Это последний рубеж защиты от злоумышленника. Без пароля выпустить новые сертификаты не получится.
# openssl genrsa -aes256 -out private/rootca.key 4096
Изменим права доступа к новому ключу, чтобы ненароком его не стереть:
# chmod 400 private/rootca.key
Откройте конфигурационный файл OpenSSL (openssl.cnf) и найдите секции [ usr_cert ] и [ v3_ca ]. Убедитесь, что в них присутствуют следующие директивы:
[ usr_cert ]# Эти расширения будут добавлены при подписывании запроса нашим УЦ.basicConstraints=CA:FALSEkeyUsage = nonRepudiation, digitalSignature, keyEnciphermentnsComment = "OpenSSL Generated Certificate"subjectKeyIdentifier=hashauthorityKeyIdentifier=keyid,issuer[ v3_ca ]# Расширения для типового УЦsubjectKeyIdentifier=hashauthorityKeyIdentifier=keyid:always,issuerbasicConstraints = CA:truekeyUsage = cRLSign, keyCertSign
Сейчас мы можем выпустить корневой сертификат удостоверяющего центра, подписав его закрытым ключом rootca.key. Так как это сертификат УЦ, используем расширение v3_ca:
# openssl req -sha256 -new -x509 -days 3650 -extensions v3_ca \
-key private/rootca.key -out certs/rootca.crt \
-subj /C=RU/ST=Moscow/L=Moscow/O=ExampleInc/OU=ITdept/CN=ca-server/emailAddress=support@example.com
# chmod 444 certs/rootca.crt
В качестве алгоритма хэширования мы используем SHA-2 (подвид SHA-256). Стоимость атаки на SHA-1 стремительно падает, а о практическом применении новоявленного SHA-3 говорить пока рано. Почему мы выбрали именно SHA-256, а не SHA-512? С сертификатом, использующим SHA-512, Вы сможете запустить демон slapd, но не сможете к нему подключиться. Увидите лишь такую многозначную ошибку:
can't connect: A TLS packet with unexpected length was received...
Мы так же указываем количество дней, в течении которых сертификат будет действителен. Десять лет — достаточно большой срок.
С помощью модификатора subj заносим в сертификат информацию:
Можем посмотреть содержимое сертификата следующей командой:
# openssl x509 -in certs/rootca.crt -noout -text
Удостоверяющий центр готов к выпуску сертификатов.
Где работаем: ldap-srv
Как правило, закрытые ключи клиентов УЦ не должны хранится в самом УЦ. Клиент может сам сформировать ключевую пару и прислать в УЦ лишь запрос на подпись (Certificate Signing Request, CSR). Запрос содержит открытый ключ. Однако мы будем создавать все ключи и хранить их в одном месте. В организации, которая серьёзно подходит к проблемам безопасности такой процесс работы может быть неприемлемым.
Продолжаем в том же каталоге /root/CA. Создадим закрытый ключ для сервера службы каталогов:
# openssl genrsa -out private/ldap-srv.example.com.key 4096 # chmod 400 private/ldap-srv.example.com.key
Сгенерируем запрос на подпись сертификата. Наименование организации (ExampleInc) должно совпадать с наименованием в корневом сертификате УЦ. В качестве Common Name укажем FQDN нашего сервера:
# openssl req -sha256 -new \ -key private/ldap-srv.example.com.key -out certs/ldap-srv.example.com.csr \ -subj /C=RU/ST=Moscow/L=Moscow/O=ExampleInc/OU=ITdept/CN=ldap-srv.example.com/emailAddress=support@example.com
Следующим шагом должно быть подписание запроса CSR существующим доверенным удостоверяющим центром (например, VeriSign) в обмен на деньги. Но нам не хочется платить за эту услугу, или у нас нет своего (корпоративного) CA, или это просто тестовая конфигурация, а может нам просто всё равно. Поэтому мы подпишем его с помощью своего собственного CA:
# openssl ca -extensions usr_cert -notext -md sha256 \ -keyfile private/rootca.key -cert certs/rootca.crt \ -in certs/ldap-srv.example.com.csr -out certs/ldap-srv.example.com.crt # chmod 444 certs/ldap-srv.example.com.crt
Создадим каталог для ключевой информации нашего сервера и поместим туда получившиеся у нас файлы:
# mkdir /etc/ldap/ssl # chown openldap:openldap /etc/ldap/ssl # chmod 0500 /etc/ldap/ssl # cp certs/ldap-srv.example.com.crt private/ldap-srv.example.com.key /etc/ldap/ssl
Установим права доступа для ключевой информации:
# chown openldap:openldap /etc/ldap/ssl/{ldap-srv.example.com.crt,ldap-srv.example.com.key}
# chmod 0400 /etc/ldap/ssl/{ldap-srv.example.com.crt,ldap-srv.example.com.key}
Поместим корневой сертификат в каталог с сертификатами операционной системы и зададим для него права доступа:
# cp certs/rootca.crt /etc/ssl/certs/ # chmod 0644 /etc/ssl/certs/rootca.crt
В заключение можем удалить запрос CSR, он нам больше не нужен:
# rm -rf certs/ldap-srv.example.com.csr
Каталог /root/CA теперь выполняет роль удостоверяющего центра. Аналогичным образом его можно создать на другой машине, тогда надо будет копировать секретные ключи и подписанные сертификаты по сети с помощью scp или через съёмный носитель. Неплохой идеей будет хранить этот каталог на отдельном носителе и монтировать его только для выпуска новых сертификатов. Сам носитель можно, например, положить в сейф. Процесс создания новых пар ключ-сертификат в будущем будет состоять из трёх этапов:
Где работаем: ldap-srv
Вернёмся во временный каталог:
$ cd ~/ldap
Создадим LDIF-файл 3.2-tls-config.ldif для внесения в каталог конфигурации TLS и запишем в него:
dn: cn=configadd: olcTLSVerifyClientolcTLSVerifyClient: never-add: olcTLSCertificateFileolcTLSCertificateFile: /etc/ldap/ssl/ldap-srv.example.com.crt-add: olcTLSCertificateKeyFileolcTLSCertificateKeyFile: /etc/ldap/ssl/ldap-srv.example.com.key-add: olcTLSCACertificateFileolcTLSCACertificateFile: /etc/ssl/certs/rootca.crt
Этими записи говорят демону slapd, где лежит его сертификат и ключ, где лежит корневой сертификат УЦ и что от клиентов требовать наличие сертификата не нужно. Чтобы окончательно всё запутать, мы могли бы создать сертификаты для всех клиентов. В реальной жизни такая аутентификация клиента принесёт небольшое усиление защиты за счёт большого увеличения работы по сопровождению всех этих сертификатов. Тем более далее в этом руководстве мы опишем механизмы аутентификации Kerberos.
Загрузим конфигурацию TLS в наш каталог:
# ldapmodify -QY EXTERNAL -H ldapi:/// -f 3.2-tls-config.ldif modifying entry "cn=config"
Теперь наш сервер OpenLDAP должен поддерживать расширения TLS. Перепроверим, что всё в порядке:
# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b cn=config -s base | grep -i tls olcTLSCertificateFile: /etc/ldap/ssl/ldap-srv.example.com.crt olcTLSCertificateKeyFile: /etc/ldap/ssl/ldap-srv.example.com.key olcTLSCACertificateFile: /etc/ssl/certs/rootca.crt olcTLSVerifyClient: never
Вновь отредактируем конфигурационный файл /etc/ldap/ldap.conf и включим поддержку TLS:
BASE dc=example,dc=comURI ldap://ldap-srv.example.comTLS_CACERT /etc/ssl/certs/rootca.crtTLS_REQCERT demandTIMELIMIT 15TIMEOUT 20
Обычно для конфигурации cn=config перезагрузка службы не требуется, но чтобы созданная нами ключевая информация подхватилась, придётся это сделать:
# service slapd restart * Stopping OpenLDAP slapd [ OK ] * Starting OpenLDAP slapd [ OK ]
Проверьте соединение с сервером с использованием TLS (модификатор -ZZ). На этот раз мы выполним запрос с использованием DN нашего администратора:
$ ldapsearch -xZZLLLWD cn=admin,dc=example,dc=com -b cn=config -s base Enter LDAP Password: dn: cn=config objectClass: olcGlobal cn: config olcArgsFile: /var/run/slapd/slapd.args olcPidFile: /var/run/slapd/slapd.pid olcTLSCACertificateFile: /etc/ssl/certs/rootca.crt olcTLSCertificateFile: /etc/ldap/ssl/ldap-srv.example.com.crt olcTLSCertificateKeyFile: /etc/ldap/ssl/ldap-srv.example.com.key olcTLSVerifyClient: never
Обратите внимание, что в запросе ldapsearch нам не пришлось указывать имя хоста (-H ldap://ldap-srv.example.com). Всё потому что оно указано в файле /etc/ldap/ldap.conf. Что касается TLS, то во время инициирования соединения клиент (на данном этапе клиентский запрос выполняет сам сервер) получает от сервера его подписанный сертификат (ldap-srv.example.com.crt). Клиент может ничего не знать о сервере, но у него есть сертификат CA (rootca.crt), с помощью которого и проверяется сервер.
Где работаем: ldap-srv
Сертификаты не вечны. Во-первых при создании задаётся его срок действия. При этом частота обновления сертификатов — баланс между безопасностью и удобством. Во-вторых он может быть скомпрометирован, если скомпрометирован его закрытый ключ. Как во втором случае оповестить субъектов доступа, что сертификат более не действителен? Для этого и служит Certificate Revocation List (CRL). Он представляет собой список серийных номеров отозванных сертификатов, подписанный УЦ, который их выпустил.
Вернёмся в каталог удостоверяющего центра:
# cd /root/CA
Прежде чем мы сможем сгенерировать CRL, надо создать файл crlnumber. Он нужен openssl, чтобы отслеживать номер следующего CRL:
# echo 1000 > crlnumber
В стандартной конфигурации openssl использует CRL V1. Раскомментируйте строку
crl_extensions = crl_extв /etc/ssl/openssl.cnf, чтобы переключиться на CRL V2. Это хорошая идея, за исключением тех случаев, когда надо использовать именно CRL V1 (например, при использовании сильно устаревшего браузера). Создаём CRL:
# openssl ca -keyfile private/rootca.key -cert certs/rootca.crt -gencrl -out crl/rootca.crl
Посмотреть результат можно так:
# openssl crl -in crl/rootca.crl -text
Предположим, что закрытый ключ сервера ldap-srv был скомпрометирован. Чтобы оповестить об этом клиентские машины, надо отозвать сертификат этого сервера, создать CRL, а затем — распространить CRL среди клиентов.
Отзываем сертификат:
# openssl ca -keyfile private/rootca.key -cert certs/rootca.crt -revoke certs/ldap-srv.example.com.crt
Заглянем в index.txt. Начало записи с нашим сертификатом теперь изменилось с V на R:
# cat index.txt R 160116072355Z 150119081313Z 1000 unknown /C=RU/ST=Moscow/O=ExampleInc/OU=ITdept/CN=ldap-srv.example.com/emailAddress=support@example.com
Обратите внимание, что копии новых сертификатов так же содержатся в каталоге newcerts. При этом имя файла содержит серийный номер сертификата. Когда отзываете сертификаты, вместо файлов в каталоге certs Вы можете пользоваться каталогом newcerts. Результат будет идентичен. Например:
# openssl ca -keyfile private/rootca.key -cert certs/rootca.crt -revoke newcerts/1000.pem
Обновим CRL:
# openssl ca -keyfile private/rootca.key -cert certs/rootca.crt -gencrl -out crl/rootca.crl
Взглянём на содержимое CRL:
# openssl crl -in crl/rootca.crl -text
Вы должны увидеть нечто подобное:
... Revoked Certificates: Serial Number: 1000 Revocation Date: ...
Поместим CRL в каталог, где его увидит клиентское ПО:
# cp crl/rootca.crl /etc/ssl
Осталось только распространить этот CRL среди клиентов. Мы делаем это простым путём — копированием файлов по сети вручную.
Где работаем: ldap-client
На каждой клиентской машине надо будет запустиь:
# scp user@ldap-srv.example.com:/etc/ssl/certs/rootca.crt /etc/ssl/certs # scp user@ldap-srv.example.com:/etc/ssl/rootca.crl /etc/ssl/
Настроим клиентскую конфигурацию в /etc/ldap/ldap.conf и укажем, где хранится CRL:
BASE dc=example,dc=comURI ldap://ldap-srv.example.comTLS_CACERT /etc/ssl/certs/rootca.crtTLS_REQCERT demandTLS_CRLFILE /etc/ssl/rootca.crlTIMELIMIT 15TIMEOUT 20
И попробуем получить доступ к серверу каталогов:
$ ldapsearch -xZZLLLWD cn=admin,dc=example,dc=com -b cn=config -s base dn ldap_start_tls: Connect error (-11) additional info: (unknown error code)
Наш CRL работает. Но к slapd теперь не подключиться. Надо выпустить новый сертификат для сервера.
Где работаем: ldap-srv
Сделаем это простой последовательностью команд. Мы повторяем пройденное, комментарии излишни:
# cd /root/CA
# openssl genrsa -out private/ldap-srv.example.com.key 4096
# chmod 400 private/ldap-srv.example.com.key
# openssl req -sha256 -new \
-key private/ldap-srv.example.com.key -out certs/ldap-srv.example.com.csr \
-subj /C=RU/ST=Moscow/L=Moscow/O=ExampleInc/OU=ITdept/CN=ldap-srv.example.com/emailAddress=support@example.com
# openssl ca -extensions usr_cert -notext -md sha256 \
-keyfile private/rootca.key -cert certs/rootca.crt \
-in certs/ldap-srv.example.com.csr -out certs/ldap-srv.example.com.crt
# chmod 444 certs/ldap-srv.example.com.crt
# cp certs/ldap-srv.example.com.crt private/ldap-srv.example.com.key /etc/ldap/ssl
# chown openldap:openldap /etc/ldap/ssl/{ldap-srv.example.com.crt,ldap-srv.example.com.key}
# chmod 0400 /etc/ldap/ssl/{ldap-srv.example.com.crt,ldap-srv.example.com.key}
Перезупустим демон slapd и убедимся, что к серверу можно подключиться:
# service slapd restart $ ldapsearch -xZZLLLWD cn=admin,dc=example,dc=com -b cn=config -s base dn Enter LDAP Password: dn: cn=config
В целом по отзыву сертификатов... Иногда в реальных условиях лучше применить другой подход. Намного удобней, когда клиентские машины самостоятельно выясняют у сервера, действителен конкретный сертификат или нет. В выпускаемые сертификаты можно вносить запись CRL Distribution Points. Она заставит клиентов самих периодически скачивать новый CRL. Или можно использовать OCSP. Но эта тема выходит за рамки данного руководства.
Где работаем: ldap-srv
На данном этапе у нас есть пустой каталог OpenLDAP. Мы можем проверить это, просто попытавшись извлечь из него информацию:
$ ldapsearch -xZZLLLWD cn=admin,dc=example,dc=com -b dc=example,dc=com Enter LDAP Password: No such object (32)
Если Вам интересно, коды ошибок LDAP описаны в RFC 4511, в приложении A Результирующие коды LDAP. В случае ошибки 32 сервер информирует нас, что запрашиваемый объект dc=example,dc=com не найден. Но такую же ошибку можно получить, если ACL сервера запрещают доступ.
Для работы нашего каталога понадобится создать корневой суффикс базы данных и добавить в него две организационных единицы (Organizational Unit, OU) для хранения пользователей и групп. Создадим LDIF-файл 4-users+groups.ldif, в котором опишем эту информацию:
dn: dc=example,dc=comdc: exampleobjectClass: topobjectClass: domaindn: ou=users,dc=example,dc=comou: UsersobjectClass: topobjectClass: organizationalUnitdescription: Central location for UNIX usersdn: ou=groups,dc=example,dc=comou: GroupsobjectClass: topobjectClass: organizationalUnitdescription: Central location for UNIX groups
Добавим эту информацию в наш каталог:
$ ldapmodify -a -xZZWD cn=admin,dc=example,dc=com -f 4-users+groups.ldif Enter LDAP Password: adding new entry "dc=example,dc=com" adding new entry "ou=users,dc=example,dc=com" adding new entry "ou=groups,dc=example,dc=com"
Можем удостовериться в том, что информация добавлена:
$ ldapsearch -xZZLLLWD cn=admin,dc=example,dc=com Enter LDAP Password: dn: dc=example,dc=com dc: example objectClass: top objectClass: domain dn: ou=users,dc=example,dc=com ou: Users objectClass: top objectClass: organizationalUnit description: Central location for UNIX users dn: ou=groups,dc=example,dc=com ou: Groups objectClass: top objectClass: organizationalUnit description: Central location for UNIX groups
Теперь давайте добавим несколько групп:
Этот список не окончательный и может быть дополнен, чтобы соответствовать нуждам Вашей организации.
Для добавления групп в каталог создадим новый LDIF, 4-groups.ldif:
dn: cn=sysadmin,ou=groups,dc=example,dc=comcn: sysadminobjectClass: topobjectClass: posixGroupgidNumber: 1100description: UNIX systems administratorsdn: cn=nssproxy,ou=groups,dc=example,dc=comcn: nssproxyobjectClass: topobjectClass: posixGroupgidNumber: 801description: Network Service Switch Proxydn: cn=test.group,ou=groups,dc=example,dc=comcn: test.groupobjectClass: topobjectClass: posixGroupgidNumber: 1101description: Test Group
Загрузим LDIF в наш каталог:
$ ldapmodify -a -xZZWD cn=admin,dc=example,dc=com -f 4-groups.ldif Enter LDAP Password: adding new entry "cn=sysadmin,ou=groups,dc=example,dc=com" adding new entry "cn=nssproxy,ou=groups,dc=example,dc=com" adding new entry "cn=test.group,ou=groups,dc=example,dc=com"
Настало время создать несколько пользователей. И вновь отмечаем, что список может быть расширен в соответствии с потребностями Вашей организации:
Создадим LDIF-файл 4-users.ldif для добавления пользователей. Пока не беспокойтесь о паролях, мы сейчас к ним вернёмся:
dn: cn=pablo,ou=users,dc=example,dc=comuid: pablogecos: Pablo SdobaobjectClass: topobjectClass: accountobjectClass: posixAccountobjectClass: shadowAccountuserPassword: {SSHA}RsAMqOI3647qg1gAZF3x2BKBnp0sEVfashadowLastChange: 15140shadowMin: 0shadowMax: 99999shadowWarning: 7loginShell: /bin/bashuidNumber: 1100gidNumber: 1100homeDirectory: /home/pablodn: cn=nssproxy,ou=users,dc=example,dc=comuid: nssproxygecos: Network Service Switch Proxy UserobjectClass: topobjectClass: accountobjectClass: posixAccountobjectClass: shadowAccountuserPassword: {SSHA}RsAMqOI3647qg1gAZF3x2BKBnp0sEVfashadowLastChange: 15140shadowMin: 0shadowMax: 99999shadowWarning: 7loginShell: /bin/falseuidNumber: 801gidNumber: 801homeDirectory: /home/nssproxydn: cn=test.user,ou=users,dc=example,dc=comuid: test.usergecos: Test UserobjectClass: topobjectClass: accountobjectClass: posixAccountobjectClass: shadowAccountuserPassword: {SSHA}RsAMqOI3647qg1gAZF3x2BKBnp0sEVfashadowLastChange: 15140shadowMin: 0shadowMax: 99999shadowWarning: 7loginShell: /bin/bashuidNumber: 1101gidNumber: 1101homeDirectory: /home/test.user
Пользователи связаны с группами через атрибут gidNumber. Для того, чтобы добавить в группу других пользователей, в запись группы необходимо добавить атрибут memberUID, перечислив в нём UID пользователей через запятую. Например, это может выглядеть вот так:
dn: cn=sysadmin,ou=groups,dc=example,dc=comcn: sysadminobjectClass: topobjectClass: posixGroupgidNumber: 1100description: UNIX systems administratorsmemberUID: 801,1101
Добавьте пользователей в каталог:
$ ldapmodify -a -xZZWD cn=admin,dc=example,dc=com -f 4-users.ldif Enter LDAP Password: adding new entry "cn=pablo,ou=users,dc=example,dc=com" adding new entry "cn=nssproxy,ou=users,dc=example,dc=com" adding new entry "cn=test.user,ou=users,dc=example,dc=com"
Теперь установим пароли для пользователей. Повторите нижеследующую команду для всех пользователей. Обратите внимание, что сначала Вам будет предложено дважды ввести пароль изменяемой записи, а затем — пароль записи cn=admin,dc=example,dc=com:
$ ldappasswd -xZZWD cn=admin,dc=example,dc=com -S cn=nssproxy,ou=users,dc=example,dc=com New password: Re-enter new password: Enter LDAP Password:
Если заглянуть в журнал /var/log/slapd.log, то можно увидеть строки, говорящие об изменении записи:
slapd[5319]: conn=1022 op=1 PASSMOD id="cn=nssproxy,ou=users,dc=example,dc=com" new slapd[5319]: conn=1022 op=1 RESULT oid= err=0 text=
Для того, чтобы пользователь nssproxy имел доступ к информации нашего каталога, необходимо поправить ACL базы данных с пользователями и группами. Но какое у этой базы DN? Давайте вспомним:
$ ldapsearch -xZZLLLWD cn=admin,dc=example,dc=com -b cn=config dn | grep -i database
Enter LDAP Password:
dn: olcDatabase={-1}frontend,cn=config
dn: olcDatabase={0}config,cn=config
dn: olcDatabase={1}mdb,cn=config
dn: olcDatabase={2}monitor,cn=config
В разделе 2.6 мы дали нашей учетной записи администратора очень широкие права, поэтому он может заглянуть в конфигурацию cn=config.
Теперь мы знаем, что требуется отредактировать ACL записи olcDatabase={1}mdb,cn=config.
Давайте проверим, какие ACL настроены для данного DN (вывод отформатирован):
$ ldapsearch -xZZLLLWD cn=admin,dc=example,dc=com -b olcDatabase={1}mdb,cn=config olcAccess
Enter LDAP Password:
dn: olcDatabase={1}mdb,cn=config
olcAccess: {0}to *
by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external ,cn=auth" manage
by * break
olcAccess: {1}to attrs=userPassword
by self write
by anonymous auth
olcAccess: {2}to *
by self read
Мы должны немного изменить ACL, чтобы предоставить доступ пользователю nssproxy на чтение атрибутов учётных записей. Для этого создадим LDIF-файл 4-nssproxy.acl.ldif:
dn: olcDatabase={1}mdb,cn=configchangetype: modifyreplace: olcAccessolcAccess: {0}to *by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external ,cn=auth" manageby * break-add: olcAccessolcAccess: {1}to attrs=userPasswordby self writeby anonymous auth-add: olcAccessolcAccess: {2}to *by self readby dn.base="cn=nssproxy,ou=users,dc=example,dc=com" read
Загрузим LDIF с изменениями:
$ ldapmodify -xZZWD cn=admin,dc=example,dc=com -f 4-nssproxy.acl.ldif
Enter LDAP Password:
modifying entry "olcDatabase={1}mdb,cn=config"
Проверим, можем ли мы просматривать информацию в каталоге от имени пользователя nssproxy. Для этого выполним запрос с использованием его учётных данных. Результатом запроса должно быть всё DIT (Directory Information Tree). Опустим его, для краткости:
$ ldapsearch -xZZLLLWD cn=nssproxy,ou=users,dc=example,dc=com "(objectClass=*)" Enter LDAP Password: dn: dc=example,dc=com ...
Убедитесь, что другие учётные записи пользователей не имеют доступа к DIT:
$ ldapsearch -xZZLLLWD cn=pablo,ou=users,dc=example,dc=com "(objectClass=*)" Enter LDAP Password: No such object (32)
База данных нашего сервера каталогов по-немногу заполняется объектами. С этого момента стоит подумать о выборе LDAP-браузера. Как правило, это приложение, которое позволяет наглядно отображать записи в базе данных и работать с ними. Лично у меня самый любимый — ldapvi. Но он консольный и имеет объективные недостатки. Попробуйте Apache Directory Studio. Он имеет нормальный GUI, бесплатен и поддерживает множество удобных функций для управления сервером каталогов. Этот браузер может быть установлен как отдельно, так и в качестве компонента программного средства Eclipse. Должен предупредить, при использовании Apache Directory Studio у меня возникали проблемы с доступом к серверу каталогов. Единственно разумное объяснение, которое я нашёл — ориентированность этого программного средства на использование с Apache Directory Server (ApacheDS). Так же неплохой вариант для работы из Windows — LDAP Admin.