HimeraSearchDB
Carding_EbayThief
triada
CrackerTuch
JustinSun

НОВОСТИ [Из песочницы] Синхронизация пользователей Zimbra Collaboration OSE на основе Active Directory

BDFpromo
Оффлайн

BDFpromo

.
.
Регистрация
23.09.18
Сообщения
12.347
Реакции
176
Репутация
0
1. Предпосылки


Настраивая сервер zimbra столкнулся с проблемой синхронизации пользователей по группе в Active Directory (AD). Если мы создаем нового пользователя в AD, то он нормально добавлялся, но если мы делаем доступ к почтовому серверу по группе, то первый раз все пользователи синхронизируются. А вот потом, изменения в группе никак не влияют на изменения пользователей почтового сервера zimbra.

Что не понравилось в статьях этих статьях, это использование скрипта на powershell (зачем, если есть ldapsearch) и постоянный вызов утилиты zmprov, и когда идет синхронизация большого количества пользователей, то скрипт выполняется продолжительное время

2. Исходные данные


ОС сервера: CentOS 7
Язык скрипта: bash
Домен Zimbra: test.ru
Сервер Zimbra: zimbra.test.local
Домен Active Directory: test.local
Группа AD для доступа к почте: mail

У пользователя может быть почта отличающаяся от его логина, такую почту вносим в AD в поле mail и по нему создаем алиас в zimbra (например вася пупкин входит в систему под логином vasia, но почту должен отправлять и получать еще как пользователь [email protected])

3. Схема работы скрипта


  1. Сохраняем в файл пользователей AD входящих в группу mail
  2. Сохраняем в файл всех пользователей zimbra со всеми атрибутами
  3. Разделяем файл со списком всех пользователей zimbra на файлы формата: имя файла — логин пользователя, содержание — атрибуты пользователя
  4. Убираем из списка пользователей zimbra системные учетные записи (admin, gal,antivirus)
  5. Сравниваем список пользователей AD и zimbra
  6. Создаем файл с командами добавления, удаления (в моем случае блокировки пользователя), синхронизации и создания алиасов
  7. Применяем данные действия в zimbra (один вызов zmprov)
  8. Отправляем отчет на почту администратору (если есть что отправлять)
  9. Удаляем временные файлы и каталоги

4. Скрипт синхронизации


У скрипта есть два режима работы — это запуск без параметров, тогда отработают только блокировка и добавление пользователей. И запуск с параметром «all», тогда будут синхронизированны все пользователи группы mail в AD.

Так же необходимо обратить внимание на использование утилиты декодирования base64 в функции синхронизации, ее необходимо использовать для полей AD в которых используются русские символы.

Сам скрипт:

#!/bin/bash
#
#1. Определение переменных
#
#1.1 Общие переменные
#Путь к рабочему каталогу
path="/mnt/zimbra/user-sync"
#Временная метка
timestamp=`date +%F-%H-%M`
#путь к временным файлам
tmp_dir=$path/tmp
#Путь к файлам с атрибутами пользователей zimbra
zim_us=$tmp_dir/zim-us
#путь к файлам логов
log_dir=$path/log
#имя лог-файла
log=$log_dir/grouplog_$timestamp.txt
#путь ко временному файлу со списком пользователей
usname=$tmp_dir/usname
#Путь к файлу со списком команд на пакетное выполнение утилитой zmprov
zmcmdfile=$tmp_dir/zmcmdfile
#путь ко временным файлам со списком атрибутов пользователей AD
userfil=$tmp_dir/userfil
#отправка почты
mutt="/usr/bin/mutt"

#
#1.2 переменные сервера zimbra
#имя домена Zimbra
domain="test.ru"
#путь к командлету zmprov
zmprov="/opt/zimbra/bin/zmprov"
#
#1.3 переменные доступа к AD по LDAP
#LDAP search
ldapsearch=/opt/zimbra/common/bin/ldapsearch
# Подключение к серверу (либо сервер, либо домен (если больше одного сервера))
ldap_server="ldap://test.local:389"
#Базовая OU поиска
basedn="DC=test,DC=local"
#Пользователь и пароль для доступа к AD по LDAP
binddn="CN=zimbra,CN=Users,DC=test,DC=local"
bindpw="qwe123" #user password
#Фильтр поиска - кто входит в группу mail
filter="(memberof=cn=mail,cn=users,dc=test,dc=local)"
#какие поля данных ищем (логин, почту и поле с не совпадающей с логином почтой для алиаса и подписи)
fields="sAMAccountName mail description displayName givenName cn sn department title"
#конец блока переменных

#Начинаем обработку

#Функции обработки
#Запись ошибки в лог
function err_log()
{
if [ $1 -eq 0 ]; then
#echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]"
#echo
echo $2" [Ok]" >> $log
else
#echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]"
#echo
echo $2" [Fail]" >> $log
fi
}

#Проверка существования каталога
function if_path ()
{
#Если каталог не существует то создаем его
if [ ! -d $1 ]; then
#Создание каталога для обработки
echo "Создание каталога $1..." >> $log
mkdir -p $1
err_log $? "Проверка каталога $1"

else
echo "Каталог обработки $1 существует" >> $log
fi
}

#Запись в файл списка пользователей из AD
function searchusersAD()
{
echo "Запись списка пользователей рассылки из AD..." >> $log
$ldapsearch -x -o ldif-wrap=no -H $ldap_server -D $binddn -w $bindpw -b $basedn $filter $fields |
grep sAMAccountName |
egrep -v '^#|^$' |
awk '{print $2}' |
sort > $usname.ad
echo "Found (Найдено) "`cat $usname.ad | wc -l`" Group in AD (групп в AD)" >> $log
}

function alluserattrzimbra()
{
#Создаем файл со списком всех пользователей и их атрибутов
$zmprov -l gaa -v $domain > $usname.gaa
#Переходим в папку где будут созданы файлы с атрибутами пользователей
cd $zim_us
#разбиваем файл со всеми пользователями на файлы, с атрибутами только одного пользователя
csplit $usname.gaa --prefix='user.' --suffix-format='%03d.zim' --elide-empty-files -s /"# name"/ '{*}'

#Переименовываем файлы по пользователям. имя берем из имени пользователя zimbra в файле
for i in $( ls $zim_us )
do
nam=`grep "# name" $zim_us/$i | awk '{ print $3}' | sed 's/@.*//g'`
mv -f $zim_us/$i $zim_us/$nam
done
cd $path
}

#Запись в файл списка пользователей из zimbra
function searchuserzimbra()
{
echo "Запись списка пользователей из zimbra..." >> $log
ls $zim_us | sort > $usname.tem
#Удаляем системные аккаунты из проверки. файл $path/system.acc содержит список системных пользователей
diff -u -i $usname.tem $path/system.acc | sed 1,3d | grep ^- | cut -c 2- | sort > $usname.zim
#rm -f $usname.tem
echo "Found (Найдено) "`cat $usname.zim | wc -l`" Group in Zimbra (групп в Zimbra)" >> $log

}

#Разница между списками пользователей (для добавления или блокировки
function diffuserlist()
{
diff -u -i $usname.zim $usname.ad | sed 1,3d | sed '/@.*/d' > $usname.diff
}

#добавление пользователей
function adduser()
{
#Проверяем существование пользователя на добавление
adddif=`grep ^+ $usname.diff | sed '1!d'`
if [ -n $adddif ];
then
for addus in $( grep ^+ $usname.diff | cut -c 2- )
do
# проверяем есть ли такой пользователь в zimbra (если есть - разблокируем, нет - создаем)
ifclos=`grep "zimbraAccountStatus:" $zim_us/$addus | awk '{print $2}' | cut -c -1`
echo "c="$ifclos"!"
if [ $ifclos = "c" ];
then
echo "ma $addus@$domain zimbraAccountStatus active" >> $zmcmdfile
echo "Пользователь $addus разблокирован" >> $tmp_dir/send.txt
if [ $addus != "" ];
then
sync_one_user $addus
fi
else
#echo $addus"-2"
echo "ca $addus@$domain" >> $zmcmdfile
echo "Пользователь $addus создан" >> $tmp_dir/send.txt
if [ $addus != "" ];
then
sync_one_user $addus
fi
fi
done

fi
}

#блокировка пользователей перед отключением
function blockuser()
{
deldif==`grep ^- $usname.diff | sed '1!d'`
if [ -n $deldif ];
then
for delus in $( grep ^- $usname.diff | cut -c 2- )
do
#zimbraAccountStatus closed
if [ $delus != "" ];
then
ifclos=`grep "zimbraAccountStatus:" $zim_us/$delus | awk '{print $2}'`
if [ "$ifclos" != "closed" ];
then
echo "user closed - $delus"
echo "ma $delus@$domain zimbraAccountStatus closed" >> $zmcmdfile
echo "Пользователь $delus заблокирован! Удалите его с сервера самостоятельно!" >> $tmp_dir/send.txt
echo $delus >> $path/close.1
cat $path/close.1 | sort > $path/close.diff
echo "$delus"
fi
fi
done
fi
}

#Функция проверки существования атрибута
function ifattr()
{
if1char=`echo $2 | cut -c -1`
if [[ -n $2 && $if1char != "" ]];
#if [ $2 != "" ];
then
#echo $2
echo -n " $1 \"$2\"" >> $zmcmdfile
fi
}

#функция синхронизации пользователя
function sync_one_user()
{
echo "Синхронизация пользователя $1..." >> $log
$ldapsearch -x -o ldif-wrap=no -H $ldap_server -D $binddn -w $bindpw -b $basedn "(sAMAccountName=$1)" $fields > $userfil/$1.ad

#Создаемначало строки атрибутов синхронизации
echo -n "ma "$1 >> $zmcmdfile

#samacc=`grep "sAMAccountName:" $userfil/$1 | awk '{print $2}'`

description=`grep "description:" $userfil/$1.ad | awk '{split ($0, a, ": "); print a[2]}'`
#echo $description
ifattr "description" "$description"

displayName=`grep "displayName:" $userfil/$1.ad | awk '{split ($0, a, ": "); print a[2]}' | base64 -d`
ifattr "displayName" "$displayName"

givenName=`grep "givenName:" $userfil/$1.ad | awk '{split ($0, a, ": "); print a[2]}' | base64 -d`
ifattr "givenName" "$givenName"

cn=`grep "cn:" $userfil/$1.ad | awk '{split ($0, a, ": "); print a[2]}'`
ifattr "cn" "$cn"

sn=`grep "sn:" $userfil/$1.ad | awk '{split ($0, a, ": "); print a[2]}' | base64 -d`
ifattr "sn" "$sn"

department=`grep "department:" $userfil/$1.ad | awk '{split ($0, a, ": "); print a[2]}' | base64 -d`
ifattr "company" "$department"

title=`grep "title:" $userfil/$1.ad | awk '{split ($0, a, ": "); print a[2]}' | base64 -d`
ifattr "title" "$title"

#Вставляем перевод строки в файле
echo >> $zmcmdfile
#Добавляем алиас
mailnew=`grep "mail:" $userfil/$1.ad | awk '{print $2}'`
if [ "$mailnew" != "" ];
then
# [ -n $mailnew ]
# echo $2
#Проверяем наличие алиаса у пользователя
#${1,,} - приводим все символы к нижнему регистру
useralias=`grep "zimbraMailAlias:" $zim_us/${1,,} | awk '{print $2}'`
if [ $useralias != $mailnew ];
then
echo "aaa \"$1@$domain\" \"$mailnew\"" >> $zmcmdfile
fi
fi
#ifattr "mail" $mailnew
# echo $mailnew
echo "Синхронизация пользователя $1 " >> $tmp_dir/send.txt

# echo "Пользователь $1 - $atrruser"

#echo "Found (Найдено) "`cat $usname.ad | wc -l`" Group in AD (групп в AD)" >> $log
}


#Выполнение скрипта
date +%F-%H-%M
#2.Проверка существования каталогов
#Корневой каталог обработки
if_path $path
#Каталог временных файлов
if_path $tmp_dir
#Каталог лог-файла
if_path $log_dir
#Каталог со списком групп
if_path $userfil
#каталог со файлами пользователей зимбра
if_path $zim_us

#Очищаем файл со списком команд на пакетное выполнение утилитой zmprov
:> $zmcmdfile
# Очищаем тело письма администратору
:> $tmp_dir/send.txt
#3.Создаем список групп рассылки из AD
searchusersAD

#4.Создаем список существующих в zimbra пользователей
alluserattrzimbra
#удаляем лишних (системных)
searchuserzimbra

#5.Сравниваем оба списка групп рассылки
diffuserlist
#Блокируем пользователей
blockuser
#Создаем или разблокируем новых пользователей
adduser

#tckb скрипту передан параметр "all" при запуске, то синхронизируем всех пользователей находящихся в группе mail AD
if [[ -n $1 && $1 = "all" ]];
then
for us in $(cat $usname.ad );
do
# echo $us
sync_one_user $us
done
fi
# запускаем выполнение всех команд утилитой zmprov из файла
$zmprov -f $zmcmdfile
# дописываем в лог файл с командами
cat $zmcmdfile >> $log
#Отправляем письмо с изменениями админу (если они есть)
if [ -s $tmp_dir/send.txt ];
then
$mutt -s "Синхронизация списка пользователей $timestamp" [email protected] -a $log < $tmp_dir/send.txt
fi

#Удаляем временные файлы и каталоги
rm -R -f $tmp_dir




5. Заключение


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

6. Ссылки


При создании данной статьи использовались идеи и статьи:

1.
2.
 
Сверху Снизу