Zimbra+LDAP

Приветствую всех обладателей Zimbra.
Не давно познакомился с этим продуктом. В итоге приняли решение его внедрять. Внедрение, разбор полетов, настройка, запуск перезапуск все легло на меня. Я довольно много шерстил по инету пока знакомился с "зеброй", неплохой хелп, даже отличный на ZimbraWiki.
Но вот работающего скрипта синхронизации ZIMBRA + LDAP так и не нашел. Но вот тут http://www.zimbra.com/forums/administrators/30856-active-directory-script-import-users-zimbra.html я нашел скрипты которые и послужили основой для моего.

Я постараюсь как можно подробней описать и рассказать как работает скрипт. Ну и надеюсь что кому то он пригодиться как пригодился мне.

И так скрипт.

#!/bin/bash

Domain="МЕГО_ДОМЕН.ру" # ДНС имя или IP адресс вашего Актив Директори
ADDOMAIN="ПОЧТА_ДОМЕН.ру" # имя домена которое у вас будет на почте например труляля@ПОЧТА_ДОМЕН.ру

#Values
LDAPSEARCH=/opt/zimbra/bin/ldapsearch # ну тут вроде бы понятно
ZMPROV=/opt/zimbra/bin/zmprov # тут вроде тоже все ясненько
DOMAIN_NAME="ПОЧТА_ДОМЕН.ру" # канечно не обезательно, но если у вас на зебре несколько доменов то тогда пригодится а так не обезательно.
TIMESTAMP=`date +%N` # красатульная и бестолковая приблудина :)
TMP_DIR=/tmp

#######################################усякие переменные куда будут заноситься данные
ADM_TMP=$TMP_DIR/ads_mail.lst
ADS_TMP=$TMP_DIR/users_ads.lst
SORT_TMP=$TMP_DIR/sort.lst
ZCS_TMP=$TMP_DIR/users_zcs.lst
DIF_TMP=$TMP_DIR/users_dif.lst
SED_TMP=$TMP_DIR/SED.lst
######################################

# Переменные номбер 2
LDAP_SERVER="ldap://МЕГО_ДОМЕН.ру" # сопсно вроде и так ясно
BASEDN="dc=МЕГО_ДОМЕН,dc=ru" # пишем по слогам
BINDDN="CN=ЗЕБРА,CN=users,DC=МЕГО_ДОМЕН,DC=ру" # вот тут указывается аккаунт для синхронизации с АД, сопсно для начало его нужно в АД создать.
BINDPW="УСИПУСИ" #это сопсно пароль к акаунту ЗЕБРА
FILTER="(mail=*)" # всякие переменные
FIELDS="mail" #-------------/-/--------------

############################################################################################################
# и так с переменными мы немного разобрались, теперь приступаем к самому сладкому. Но прежде чем что-то говорить я опишу сам процес синхронизации на пальцах.
#И поясню почему именно так а не иначе.
#Так как у меня в организации, есть логин и почта, а зачастую они разные (внимание это главная фича). Аутентификация в зибре проходит только по логину
# (внимание ТОЛЬКО ПО ЛОГИНУ!!!!) и паролю из АД. Вопрос что делать если логин и имя почты у данного пользователя разные? Вееееерно создать ALIAS.
#Теперь финт ушами. В "ЗЕБРЕ" мы создаем аккаунт (это будет ниже показано) с логином от АД а в его алиас мы записываем его email который указан в АД.
#Догнали? если нет читаем заного.
#Так вот прикол в том что когда пользователь будет заходить на почту то он будет указывать имя своей почты которое в АД. НО!!!! пароль он будет вносить от ЛОГИНА.
#Как он пройдет аутентификацию то попадет на основной акаунт (который логин а АД) но в настройках мы можем указать что мол основная почта с которой он будет отправлять
#это будет не что иное как его alias который точно такой же как и его email в АД.
#
# Я все понимаю, что это бред сивой кабылы, что бредятене хуже некуда и что это не понятно, и вообще мол зачем так извращаться. Дело в том что ну не хотят пользователи
#менять свою почту, а логины и email не у всех одинаковые.
#Громадный плюс всего этого это канечно то что если вы пользователя заблочили, то и почта заблочилась тут же :) "коваааарно". Ну это конечна не единственный плюс
#
#Ну хватит слов давайте считать что вы поняли основную идею и теперь её осталось воплотить. И так, К ДЕЛУ!!!
#############################################################################################################

# Сначала выгружаем почту с АД мы же не хотим вносить всех пользователей. А вносим только тех у кого есть мыло
echo -n "Выгружение почты с AD... "
$LDAPSEARCH -x -H $LDAP_SERVER -b $BASEDN -D "$BINDDN" -w $BINDPW "$FILTER" $FIELDS | \
grep "@$DOMAIN_NAME" | \
awk '{print $2}' | \
sort > $ADM_TMP
echo "Found `cat $ADM_TMP | wc -l` users ($ADM_TMP)"

# Следующий шаг мы ищем в АД почту (которую мы уже выгрузили) в запоминаем её sAMAccountName (логин)
echo -n "POISK: "
cat $ADM_TMP | wc -l
for x in $(cat $ADM_TMP | sed s/^+//g);
do
echo -n " $x ";
#тут я решил показать подробно как все устроено
sv=`ldapsearch -x -h МЕГО_ДОМЕН.ру -b dc=МЕГО_ДОМЕН,dc=ру -D "cn=ЗЕБРА,cn=users,dc=МЕГО_ДОМЕН,dc=ру" -w "УСИПУСИ" -LLL "(mail=$x)" sAMaccountName | grep sAMAccountName `
un=`echo -n $sv | grep -w sAMAccountName: | awk '{split ($0, a, "sAMAccountName: "); print a[2]}' | awk '{print $1}'` # таким образом получаем чистый логин
un1=`echo -n $un@$DOMAIN_NAME` # сопсно к логину добавляем @ПОЧТА_ДОМЕН.ру

# все это дело записываем в фаил
RES=$?
if [ "$RES" == "0" ]; then echo -n $un1 | sort >> $ADS_TMP ; else echo "[Err]"; fi
done
sort $ADS_TMP > $SORT_TMP # А теперь мы этот фаил сортируем по алфовиту. Это очень важно.

# Теперь выгружаем всех пользователей (аккаунты) с zimbra это нужно для составления файла, чтобы добавлять или удалять новых или старых пользователей.
$ZMPROV -l gaa $DOMAIN_NAME | sort > $ZCS_TMP
echo "Found `cat $ZCS_TMP | wc -l` users ($ZCS_TMP)"

# Теперь у нас есть 2 файла 1 с АД другой с зимброй. Сравниваем их если есть почта в Зибмре но её нет в АД ставим -.
#Если наоборот ставим + если не то не другое ничего не ставим :)
echo "Generating diff file ($DIF_TMP)"
diff -u $ZCS_TMP $SORT_TMP | grep "$DOMAIN_NAME" > $DIF_TMP # и канечно результат записываем в другой фаил

#####################################################
#И так первый этап мы прошли у нас есть фаил в котором есть логин из АД, которые будет являться основной почтой (аккаунтом) в зимбре по которому будет проходит
#проверка подлинности (это так в зимбре называется)
#следующим шагом у нас идет занесение ALIAS для опредленных пользователей. Так как в АД нет таких записей как логин@ПОЧТА_ДОМЕН.ру
#у меня например ПОЧТА_ДОМЕН.ру и МЕГО_ДОМЕН.ру одинаковые. Но в любовм случаи нам нужно в файле $DIF_TMP убрать @ПОЧТА_ДОМЕН.ру
# потому как мы будем производить поиск по логинам из АД, для выгрузки поля email ( в зимбре это будешт наш alias для этих пользователей)
######################################################
sed '/@ПОЧТА_ДОМЕН.ру/s/@ПОЧТА_ДОМЕН.ру//g' $DIF_TMP > $SED_TMP # результат записываем в фаил.

# Теперь шерстим этот фаил. Если напротив логина стоит + мы ищем поле email для этого логина в АД и заносим его в Зимбру а найденый email как ALIAS для этого логина
echo -n "New USER: "
cat $SED_TMP | grep ^+ | wc -l
for i in $(cat $SED_TMP | grep ^+ | sed s/^+//g);
do
echo -n " - Adding $i ";
searchValues1=`ldapsearch -x -h $Domain -b $BASEDN -D $BINDDN -w $BINDPW -LLL "(sAMAccountName=$i)" mail`
Username=`echo $searchValues1 | grep -w mail: | awk '{split ($0, a, "mail:"); print a[2]}' | awk '{print $1}'`

printf "Creating User $Username \n"; # эту строку можно закоментить просто она удобна при отладки
$ZMPROV ca $i"@ПОЧТА_ДОМЕН.ру" passwd > /dev/null; # создаем основной аккаунт на зимбре но без пароля, так как у нас будет настроена в зимбре проверка подлинности
$ZMPROV aaa $i"@ПОЧТА_ДОМЕН.ру" $Username; # вносим ALIAS для этого аккаунта
RES=$?
if [ "$RES" == "0" ]; then echo "[Ok]"; else echo "[Err]"; fi
done

# Эта часть отвечает за удаление пользователей из зимбры. То есть есть ли есть пользователь в зимбре но его нет в АД то из зимбры он удаляется
# В данный момент у меня пока идет прибавление пользователей.
#echo -n "Old users: "
#cat $DIF_TMP | grep ^- | wc -l
#for i in $(cat $DIF_TMP | grep ^- | sed s/^-//g);
#do
#echo -n " - Deleting $i ";
#$ZMPROV deleteAccount $i > /dev/null;
#RES=$?
#if [ "$RES" == "0" ]; then echo "[Ok]"; else echo "[Err]"; fi
#done

# удаление файлов обработки удобно их просматривать при дебаге.
#rm -f $ADM_TMP
#rm -f $ADS_TMP
#rm -f $SORT_TMP
#rm -f $ZCS_TMP
#rm -f $DIF_TMP
#rm -f $SED_TMP

Ну вот вроде бы и весь скрипт. Заранее прошу за ошибки. Если что не ясно или я что-то не четко описал или написал. Пишите на все вопросы отвечу. По поводу что тут много всяких переменных я знаю. Просто когда отлаживал использовал их всех бывает что одна переменная не работает как надо 2 раза подрят это же Linux ^_^. В общем бубен это БУБЕН.

P.S. желаю всем удачного дня. И стабильной работы. Сайт мне понравился буду сюда теперь часто заглядывать.

P.p.S.s я тут почитал повнимательнее и подумал что внести некоторое объяснение будет весьма кстати.
Допустим у меня в АД есть:
Пользователь Вася Пупкин Медведевич
Его логин (sAMAccountName) vasiazubr
Пароль на его логин 3.14zdec
и также у него есть есть почта vasiok@МЕГО_ДОМЕН.ру

Как видно из исходных данных его логин и его почта разные.
После того как мы прогоним скрипт сделается следующее.
В zimbre появиться:
пользователь vasiazubr@ПОЧТА_ДОМЕН.ру
у него будет alias vasiok@ПОЧТА_ДОМЕН.ру (в данном случаи я подставляю переменные но у нас ПОЧТА_ДОМЕН и МЕГО_ДОМЕН это одно и тоже)
и пароль для входа в zimbra у него будет 3.14zdec (так как мы настроем проверку подлинности)
Вывод.
Данный пользователь может зайти в zimbr-у как под vasiazubr так и под vasiok пароль будет один и тот же. Он попадает в основную почту vasiazubr@ПОЧТА_ДОМЕН.ру
НО! чтобы он отправлял свою почту от vasiok@ПОЧТА_ДОМЕН.ру придется ручками поправить в настройках его адрес с которого буду уходить письма. И тогда все будет четко.

Но в основном всегда старайтесь логин и почта должны быть одинаковыми, потому как ЕКСЧАНДЖ делает так.

Теперь думаю что будет куда более понятней.

Комментарии

avasyukov аватар

Масштабно. Может стоит перенести в статьи на основной портал? Там оно сохранится, а здесь постепенно утонет и затеряется.

Канечно выложу и напишу.
Вот тока сделаю его покрасивее. С картинками
с командочками с выводами всякими и тут же запостю.

В строках этих все ли корректно? Пишет что ldapsearch: Command not found

sv=`ldapsearch -x -h МЕГО_ДОМЕН.ру -b dc=МЕГО_ДОМЕН,dc=ру -D "cn=ЗЕБРА,cn=users,dc=МЕГО_ДОМЕН,dc=ру" -w "УСИПУСИ" -LLL "(mail=$x)" sAMaccountName | grep sAMAccountName `
searchValues1=`ldapsearch -x -h $Domain -b $BASEDN -D $BINDDN -w $BINDPW -LLL "(sAMAccountName=$i)" mail`

После замены 'ldapsearch' на '$LDAPSEARH' заработало, но пишет такие вещи:

 - Adding USER1 Creating User USER1@postdomain.ru
ERROR: account.NO_SUCH_ACCOUNT (no such account: USER1@postdomain.ru)
[Err]
 - Adding USER1 Creating User USER1@postdomain.ru
ERROR: account.ACCOUNT_EXISTS (email address already exists: USER1@postdomain.ru, at DN: uid=USER1,ou=people,dc=postdomain,dc=ru)
[Err]

И работает крайне медленно.
Пользователи в зимбру добавляются.

 

averonsa wrote:
В строках этих все ли корректно? Пишет что ldapsearch: Command not found
sv=`ldapsearch -x -h МЕГО_ДОМЕН.ру -b dc=МЕГО_ДОМЕН,dc=ру -D "cn=ЗЕБРА,cn=users,dc=МЕГО_ДОМЕН,dc=ру" -w "УСИПУСИ" -LLL "(mail=$x)" sAMaccountName | grep sAMAccountName `
searchValues1=`ldapsearch -x -h $Domain -b $BASEDN -D $BINDDN -w $BINDPW -LLL "(sAMAccountName=$i)" mail`

После замены 'ldapsearch' на '$LDAPSEARH' заработало, но пишет такие вещи:

 

я выкладывал работающий вариант у меня вот так и как бы работает. Есть один нюанс. Скрипт надо запускать под пользователем Zimbra (по дефолту у него пароля нет)
потому что такие команды как ldapsearch или zmrov это команды чисто зимбровские (ldap она использует свой) поэтому может что-то не так отработать. А если запустишь от пользователя zimbra то можно оставить вот так ldapsearch :)

averonsa wrote:

 - Adding USER1 Creating User USER1@postdomain.ru
ERROR: account.NO_SUCH_ACCOUNT (no such account: USER1@postdomain.ru)
[Err]
 - Adding USER1 Creating User USER1@postdomain.ru
ERROR: account.ACCOUNT_EXISTS (email address already exists: USER1@postdomain.ru, at DN: uid=USER1,ou=people,dc=postdomain,dc=ru)
[Err]

И работает крайне медленно.
Пользователи в зимбру добавляются.

 

Да пишет все верно. ERROR: account.ACCOUNT_EXISTS (email address already exists: USER1@postdomain.ru, at DN: uid=USER1,ou=people,dc=postdomain,dc=ru) это означает то что логин пользователя и его почта совпадают и они одинаковые(то есть alias он тоже может быть только единожды индивидуалым). Для понятия сделай пользователю с логином vasia почту петя@ и тогда увидешь что ошибка эта не будет выскакивать. насчет медлительности, что есть то есть. Сама команда zmrov действительно отрабатывает медленно даже если её вводить в ручную.

Понел :idea:

Подобное решение на Перле нашел на www.opennet.ru для 6 и 7 версий. Потребуется установка модуля libnet-ldap-perl. Всем удачи.