Tips & Triks

не ломается у того, кто ничего не делает...

Репликация LDAP с поддержкой kerberos

, ,

Что такое репликация и зачем она нужна, в этой статье вы не найдете,
здесь я расскажу только о том как настроить репликацию используя
для авторизации слэйвов только 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

Перед запуском утилиты на 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

OSPF поверх GRE туннелей в linuxMailman - найдется все. Полнотекстовый поиск по рассылке.

Comments

Unregistered user Wednesday, September 22, 2010 1:01:12 PM

sash-kan writes: >Существовала инфраструктура, настроенный ldap с авторизацией >клиентов к нему только по kerberos, никаких логин-паролей, никаких >специальных админских учеток в ldap не было. описать инфраструктуру не планируете?

Zl0 Wednesday, September 22, 2010 6:36:15 PM

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

Unregistered user Thursday, September 30, 2010 1:55:07 PM

Аноним writes: если можно киньте ссылку на английский вариант(если он у вас использовался при создании)

Zl0 Monday, October 4, 2010 8:48:55 AM

http://www.rjsystems.nl/en/2100.php
вот здесь одни из самых приличных руководств, которые мне встречались, но я при создании ими не пользовался, на них наткнулся уже много позже.

Write a comment

New comments have been disabled for this post.

June 2012
M T W T F S S
May 2012July 2012
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30