Ключевые слова:ldap, replication, auth, kerberos, (найти похожие документы)
From: ZIO
Date: Mon, 23 Oct 2010 17:02:14 +0000 (UTC)
Subject: Репликация LDAP с поддержкой kerberos
Оригинал: http://my.opera.com/Zl0/blog/2010/09/20/syncrepl-ldap-kerberos-support
Что такое репликация и зачем она нужна, в этой статье вы не найдете,
здесь я расскажу только о том как настроить репликацию используя
для авторизации слэйвов только kerberos, а так же некоторые вещи
которые чаще всего пропускаются в статьях про репликацию, и лично
у меня вызывали вопросы.
Существовала инфраструктура, настроенный ldap с авторизацией
клиентов к нему только по kerberos, никаких логин-паролей, никаких
специальных админских учеток в ldap не было. И были еще несколько
slave серверов, которые реплицировались по средством
slapcat->scp->replace ldapDB.
Неудобно жутко, захотелось чтобы все изменения сразу разливались
по slave, хоть изменений вносилось и немного, но актуализация данных
нужна.
Выбор пал на syncrepl, опять же, "почему?" можно почитать в других
статьях.
Как его настроить вроде тоже не сложно, с master вообще сначала
вопросов не возникло, но только сначала. Со slave начались вопросы "A
кого указывать authcid, у меня же kerberos? Укажу принципла, как он
получит тикет?"
Все вопросы не буду расписывать, распишу только решение с
комментариями, как сделать чтобы работало, и безопасность не
пострадала. Начну наоборот со SLAVE, т.к будет проще понять что и
зачем.
[slapd.conf]
# Назовем его псевдопользователем, потому что как таковой
# этой записи в директории нет, и не будет, но тот кто
# будет авторизовываться под этим именем будет иметь все
# права на базу. Подробнее об этом будет ниже.
rootdn "cn=replicator,dc=domain,dc=ru"
# Индексы базы, первая запись просто для ускорения поиска
# по базе, вторая для создания уникальных uid, используется
# в репликации
index objectClass,uid,uidNumber,gidNumber,memberUid eq
index entryCSN,entryUUID eq
# Это маска, для авторизации наших slave.
authz-regexp "uid=[^,]*/replicator,cn=gssapi,cn=auth"
"cn=replicator,dc=domain,dc=ru"
# База только на чтение, этот параметр не влияет на то, сможет
# ли репликатор обновлять данные в базе, скажу что сможет.
readonly on
# Описание самой репликации.
syncrepl rid=111
provider=ldap://master.domain.ru:389/
type=refreshAndPersist
retry="60 +"
searchbase="dc=domain,dc=ru"
schemachecking=off
starttls=yes
bindmethod=sasl
saslmech=gssapi
realm=domain.ru
authcid="ldap-slave1/replicator@DOMAIN.RU"
# Куда переправлять запросы на запись, если кто-то попытается
# сделать запись на этот slave
updateref ldap://master.domain.ru
Теперь подробнее о том как получается replicator.
Для каждого slave сервера необходимо создать на KDC
по дополнительному принциплу.
ktadd -randkey ldap-slave1/replicator@DOMAIN.RU
ktadd -randkey ldap-slave2/replicator@DOMAIN.RU
Именно такие принциплы при обращение к мастеру будут, с помощью
authz-regexep матчиться в юзера replicator, который
в конфиге у нас rootdn , т.е пользователь со всеми правами
на базу. В начале я дал ему даже специально права на запись.
#access to *
# by ssf=128 dn="cn=replicator,dc=domain,dc=ru" write
# by * break
но потом это оказалось излишне.
Как заставить slave использовать kerberos для авторизации
как ldap клиент?
Оказалось есть уже специальная тулза, которая умеет
использовать keytab, получать тикет и обновлять его, после того
как он протухнет.
aptitude install kstart
Пришлось ей написать правильный init скрипт, он прилагается.
k5start-init
#! /bin/sh
# /etc/init.d/k5start: start the kernel log daemon.
### BEGIN INIT INFO
# Provides: k5start
# Required-Start: $syslog
# Required-Stop: $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Kinit
### END INIT INFO
PATH=/bin:/usr/bin:/sbin:/usr/sbin
pidfile=/var/run/k5start.pid
binpath=/usr/bin/k5start
keytab=/etc/ldap/replicator.keytab
oid=$(cat /etc/passwd |grep openldap | cut -d: -f3)
test -f $binpath || exit 0
. /lib/lsb/init-functions
case "$1" in
start)
log_begin_msg "Starting k5start daemon..."
start-stop-daemon --start --pidfile $pidfile \
--exec $binpath -- -p $pidfile \
-U -f $keytab -b -K 10 -l 8h -k /tmp/krb5cc_${oid} -o openldap
log_end_msg $?
;;
stop)
log_begin_msg "Stopping k5start daemon..."
start-stop-daemon --stop --pidfile $pidfile
rm -f $pidfile && rm -f /tmp/krb5cc_${oid}
log_end_msg $?
;;
restart|force-reload)
log_begin_msg "Reloading k5start daemon..."
/etc/init.d/k5start stop
/etc/init.d/k5start start
log_end_msg $?
;;
*)
log_success_msg "Usage: /etc/init.d/k5start {start|stop|restart|force-reload
}"
exit 1
esac
exit 0
Перед запуском утилиты на slave нужно получить тот самый keytab
для принципла и поставить ему правильные права.
kadmin -p mylogin/admin -q "ktadd -k /etc/ldap/replicator.keytab ldap-slave1/replicator@DOMAIN.RU"
chown openldap:openldap /etc/ldap/replicator.keytab
chmod 600 /etc/ldap/replicator.keytab
Если сохранили под другим именем и/или в другом месте, не забудьте
подправить переменную keytab в init-скрипте.
Аналогичные действия делаются на всех slave, для каждого свой keytab,
в названии я использовал имя хоста, можно в принципе что угодно,
главное чтобы маска соблюдалась (hostname/replicator), можно и вообще
использовать один keytab на всех, но уже 1) не секурно 2) в логах
будет путаница.
После запуска k5start в /tmp/ должны увидеть кэш тикета нашего
openldap пользователя.
#ls -la /tmp
total 16
drwxrwxrwt 3 root root 4096 Sep 20 18:42 .
drwxr-xr-x 22 root root 4096 Jul 19 2009 ..
-rw------- 1 openldap openldap 960 Sep 20 13:42 krb5cc_104
На slave должно быть все готово, можно переходить к master.
MASTER
[slapd.conf]
# Загружаем модули
moduleload syncprov
# Строим индексы
index entryCSN,entryUUID eq
# Матчим наших прициплов со slave серверов, в
# полноценного пользователя с особыми правами.
authz-regexp "uid=[^,]*/replicator,cn=gssapi,cn=auth"
"cn=replicator,dc=domain,dc=ru"
# Включаем репликацию.
overlay syncprov
syncprov-checkpoint 50 10
syncprov-sessionlog 100
# Replicator должен иметь права на то чтобы читать всю базу, ну или какую то
# ветку, если он реплицирует тольчасть дерева.
access to *
by peername.ip="192.168.1.0%255.255.255.0" sasl_ssf=56 dn="cn=replicator,dc=domain,dc=ru" read
by peername.ip="192.168.2.0%255.255.255.0" sasl_ssf=56 dn="cn=replicator,dc=domain.ru,dc=ru" read
by peername.ip="192.168.32.0%255.255.252.0" sasl_ssf=56 dn="cn=replicator,dc=domain,dc=ru" read
by * break
На master никаких kstart запускать не нужно, он ждет только клиентов,
и проверяет их валидность через kerberos.
Если все готово перезапускаем службы на master, потом на slave
внимательно смотрим в лог, ищем похожую строчку
master slapd[11612]: conn=4 op=3 BIND authcid="ldap-slave1/replicator" authzid="ldap-slave1/replicator"
master slapd[11612]: conn=4 op=3 BIND dn="cn=replicator,dc=domain,dc=ru" mech=GSSAPI sasl_ssf=56 ssf=128
Которая говорит нам что slave удачно авторизовался и правильно
заматчился.
После этого можно вносить изменения на master, и смотреть как они
почти моментально принимаются на slave серверах. Кстати, так же можно
запускать slave сервера совсем без базы, если все правильно настроено,
вся база сразу же после запуска реплицируется с master на slave.
Правильно работающая репликая должна оставлять логи примерно такого
содержания
[Loglevel debug]
slapd[3003]: send_ldap_result: conn=-1 op=0 p=0
slapd[3003]: send_ldap_result: err=0 matched="" text=""
slapd[3003]: syncrepl_entry: rid=222 be_search (0)
slapd[3003]: syncrepl_entry: rid=222 uid=user_test,o=TEST,dc=domain,dc=ru
slapd[3003]: slap_queue_csn: queing 0xb5c025e8 20100920155901.638546Z#000000#000#000000
slapd[3003]: bdb_modify: uid=user_test,o=TEST,dc=domain,dc=ru
slapd[3003]: bdb_dn2entry("uid=user_test,o=test,dc=domain,dc=ru")
slapd[3003]: bdb_modify_internal: 0x000000e5: uid=user_test,o=TEST,dc=domain,dc=ru
slapd[3003]: <= acl_access_allowed: granted to database root
slapd[3003]: bdb_modify_internal: replace mail
slapd[3003]: bdb_modify_internal: replace entryCSN
slapd[3003]: bdb_modify_internal: replace modifiersName
slapd[3003]: bdb_modify_internal: replace modifyTimestamp
slapd[3003]: => key_change(DELETE,e5)
slapd[3003]: bdb_idl_delete_key: e5 [5efbbb83]
slapd[3003]: <= key_change 0
slapd[3003]: => key_change(DELETE,e5)
slapd[3003]: bdb_idl_delete_key: e5 [7faff89e]
slapd[3003]: <= key_change 0
slapd[3003]: => key_change(DELETE,e5)
.......................................................
slapd[3003]: => key_change(ADD,e5)
slapd[3003]: bdb_idl_insert_key: e5 [acbfa9c7]
slapd[3003]: <= key_change 0
slapd[3003]: => key_change(ADD,e5)
slapd[3003]: bdb_idl_insert_key: e5
slapd[3003]: <= key_change 0
slapd[3003]: => entry_encode(0x000000e5): uid=user_test,o=TEST,dc=domain,dc=ru
slapd[3003]: bdb_modify: updated id=000000e5 dn="uid=user_test,o=TEST,dc=domain,dc=ru"
slapd[3003]: send_ldap_result: conn=-1 op=0 p=0
slapd[3003]: send_ldap_result: err=0 matched="" text=""
slapd[3003]: slap_graduate_commit_csn: removing 0xb5c13ba8 20100920155901.638546Z#000000#000#000000
slapd[3003]: syncrepl_entry: rid=222 be_modify (0)
slapd[3003]: slap_queue_csn: queing 0xb5c025e8 20100920155901.638546Z#000000#000#000000
О чем это говорит, что slave узнал что данные изменились, ключики
удалились, новые ключики добавились,
транзакция закоммитилась.
Что нужно помнить, что может вылезти и как это лечить.
1. Не забывать сделать индексы, а именно sudo -u openldap slapindex
2. Если replicator не мачится по regex, возможно в slapd.conf
у вас есть параметры
sasl-realm DOMAIN.RU
sasl-host kdc.domain.ru
в таком случае к принциплу при авторизации будет добавлен еще cn=sasl,
т.е
regex нужно поправить.
authz-regexp "uid=[^,]*/replicator,cn=sasl,cn=gssapi,cn=auth" "cn=replicator,dc=domain,dc=ru"
3. Backends на master и slave должны быть одинаковы hdb<->hdb,
bdb<->bdb
4. Ошибки типа "warning: SASL authentication problem: unable to open
Berkeley db /etc/sasldb2: Permission denied"
лечится
chown root:sasl /etc/sasldb2
chmod 660 /etc/sasldb2
5. Убедитесь что cache тикета на слейвах периодически обновляется,
время создания файла должно обновляться.
Переодичность обновления выставляется в init скрипте k5start
6. При отладке не забывать включать loglevel debug в slapd.conf
# Level debug
loglevel 32767