Создание и обновление списков рассылки в Zimbra Collaboration OSE на основе групп и пользователей Active Directory

  • Tutorial
image

1. Пара слов от автора


Статья обновлена. Скрипты изменены. Добавлен скрипт для обновления одного списка рассылки.

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

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


ОС сервера: CentOS 7

По поводу ОС
На самом деле разница между CentOS7 и любой другой системой будет заключаться исключительно в командах серверу на установку пакетов, и, возможно, расположении некоторых файлов. Работа ведется в основном с командлетами Zimbra, так что отличия настройки будут минимальны.

Домен Zimbra: zimbramail.home.local
Путь монтирования шары на хосте Zimbra: /mnt/ZM/

3. Настройка


  1. Монтируем шару Windows к нашему Linux серверу. Это нужно для упрощения и автоматизации передачи данных из Windows PowerShell в Linux Bash. Процедура монтирования была описана в предыдущей статье. Не буду повторяться.
  2. Создаем в AD отдельное OU, в котором создаем группы, на основе которых будут созданы списки рассылки в Zimbra. Имя группы = имя списка рассылки.
  3. Добавляем в группы, созданные в новом OU, пользователей или группы безопасности, на основе которых будут наполняться списки рассылки в Zimbra. Скрипт отрабатывает рекурсивно, что значит, что он соберет все данные о пользователях, состоящих в группах, которые добавлены в группы в целевом OU. Подробнее о выводе команды Get-ADGroupMember.
  4. Создаем скрипт сбора данных из Active Directory.
  5. Создаем скрипт добавления листов рассылки и их наполнения пользователями на основе полученных данных в предыдущем скрипте.
  6. Наслаждаемся.


3.1. По поводу OU


Я создал OU “ZimbraDL” в корне домена и запретил ему наследование групповых политик, чтобы эти группы оставались обособленными. Они не будут участвовать в жизни домена никак, помимо формирования Distribution Lists в Zimbra Collaboration OSE.

4. Скрипт на PowerShell для сбора данных из AD


Скрипт PowerShell
$Path = "C:\ZM\ZimbraDL"
$enc = [system.text.encoding]
function ReCode ( $f, $t, $line ) 
{
    $cp1          = $enc::getencoding( $f )
    $cp2          = $enc::getencoding( $t )
    $inputbytes   = $enc::convert( $cp1, $cp2, $cp2.getbytes( $line ))
    $outputstring = $cp2.getstring( $inputbytes )
    $outputstring | add-content $OutputFile
}

#Очистка каталога
if(test-path $Path)
{ 
    Remove-Item $Path -Recurse -Force 
}

#Создание рабочих директорий
if(!(Test-Path $Path))
{
    New-Item -ItemType Directory -Force -Path $Path
}
if(!(Test-Path $Path\Groups))
{
   New-Item -ItemType Directory -Force -Path $Path\Groups
}
if(!(Test-Path $Path\Users))
{
   New-Item -ItemType Directory -Force -Path $Path\Users
}
if(!(Test-Path $Path\UsersTemp))
{
    New-Item -ItemType Directory -Force -Path $Path\UsersTemp
}

#Создание списка групп
Import-Module ActiveDirectory
Get-AdGroup -filter * -SearchBase "OU=ZimbraDL,DC=home,DC=local" | select samaccountname | Out-File $Path\Groups\GetGroupsAD.txt

#Форматирование списка групп
(Get-Content "$Path\Groups\GetGroupsAD.txt") -notmatch "samaccountname" | where {$_ -ne ""} | where {$_ -ne "--"} | Where-Object {$_ -notmatch '-'} | out-file "$Path\Groups\GetGroupsAD.txt"
$File = @(Get-Content $Path\Groups\GetGroupsAD.txt)
foreach ($File1 in $File) 
{
    $string=$File1.TrimStart('"')
    $string=$string.TrimEnd('"')
    $string=$string.TrimStart(' ')
    $string=$string.TrimEnd(' ') | Out-File $Path\Groups\GroupsListTemp.txt -Append
}

#Удаление временного файла
Remove-Item $Path\Groups\GetGroupsAD.txt -Force

$InputFile = gc $Path\Groups\GroupsListTemp.txt
$OutputFile = "$Path\Groups\GroupsList.txt"

#Исправление кодировки
foreach ($line in $InputFile) 
{
    ReCode -f "windows-1251" -t "utf-8" $line
}

#Удаление временного файла
Remove-Item $Path\Groups\GroupsListTemp.txt -Force
 
#Создание файлов со списком пользователей для каждой группы
$GroupName = @(Get-Content $Path\Groups\GroupsList.txt)
Foreach ($Group in $GroupName)
{
    Get-ADGroupMember $Group -recursive | ft SamAccountName | out-file "$Path\UsersTemp\$Group.txt" -Append
    (get-content "$Path\UsersTemp\$Group.txt")  -notmatch "Name" | where {$_ -ne ""} | where {$_ -ne "--"} | Where-Object {$_ -notmatch '-'} | out-file "$Path\UsersTemp\$Group.txt"
    $File=@(Get-Content $Path\UsersTemp\$Group.txt)
    foreach ($File1 in $File) 
    {
        $string=$File1.TrimStart('"')
        $string=$string.TrimEnd('"')
        $string=$string.TrimStart(' ')
        $string=$String.TrimEnd(' ') | Out-File "$Path\UsersTemp\$Group" -Append
    }
    $InputFile = gc $Path\UsersTemp\$Group
    $OutputFile = "$Path\Users\$Group"

    #Исправление кодировки
    foreach ($line in $InputFile) 
    {
        ReCode -f "windows-1251" -t "utf-8" $line
    }
}

#Очистка лишних временных директорий
Remove-Item "$Path\UsersTemp\" -Recurse -Force
Remove-Item "$Path\Groups" -Recurse -Force


4.1. Как работает скрипт


  1. Сначала происходит проверка существования и удаление рабочей директории, если она существует. Это нужно, чтобы в процессе работы данные не задвоились.
  2. PoSh смотрит в указанное OU, считывает группы пользователей, находящиеся в нем и записывает их в файл GetGroupsAD.txt
  3. Отбрасывает из полученного файла все лишнее (PoSh пишет в файл весь свой вывод, так что в изначальном выводе команды первой строкой идет Name, второй строкой разделитель "----", и только после этого перечисляются группы по одной на строку), меняет кодировку с «windows-1251» на utf-8, результатом чего является другой файл GroupsList.txt
  4. Далее на основе полученного файла считывается информация о пользовтелях групп, содержащихся в файле. Файлы, содержащие в себе имена пользователей (samAccountName)
    помещаются в директорию \Users и называются по именам групп


4.2. Скрипт для считывания информации с отдельно взятой группы


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

Скрипт PowerShell для запуска руками с возможностью считать данные только одной группы
$Path = "C:\ZM\ZimbraDL"
$enc = [system.text.encoding]
function ReCode ( $f, $t, $line ) 
{
    $cp1          = $enc::getencoding( $f )
    $cp2          = $enc::getencoding( $t )
    $inputbytes   = $enc::convert( $cp1, $cp2, $cp2.getbytes( $line ))
    $outputstring = $cp2.getstring( $inputbytes )
    $outputstring | add-content $OutputFile
}

#Очистка каталога
if(test-path $Path)
{ 
    Remove-Item $Path -Recurse -Force 
}

#Создание рабочих директорий
if(!(test-path $Path))
{
    New-Item -ItemType Directory -Force -Path $Path
}
if(!(Test-Path $Path\Groups))
{
   New-Item -ItemType Directory -Force -Path $Path\Groups
}
if(!(Test-Path $Path\Users))
{
   New-Item -ItemType Directory -Force -Path $Path\Users
}
if(!(Test-Path $Path\UsersTemp))
{
    New-Item -ItemType Directory -Force -Path $Path\UsersTemp
}

#Создание списка групп
Import-Module ActiveDirectory
$Groupname = Read-Host 'Введите имя группы, которую нужно обновить, или ALL для обновления всех списков рассылки'
If ($Groupname -eq "ALL")
{
    Get-AdGroup -filter * -SearchBase "OU=ZimbraDL,DC=home,DC=local" | select samaccountname | Out-File $path\Groups\GetGroupsAD.txt
}
Else
{
    $Groupname > "$Path\Groups\GetGroupsAD.txt"
}    

#Форматирование списка групп
(Get-Content "$Path\Groups\GetGroupsAD.txt") -notmatch "samaccountname" | where {$_ -ne ""} | where {$_ -ne "--"} | Where-Object {$_ -notmatch '-'} | out-file "$Path\Groups\GetGroupsAD.txt"
$File = @(Get-Content $Path\Groups\GetGroupsAD.txt)
foreach ($File1 in $File) 
{
    $string=$File1.TrimStart('"')
    $string=$string.TrimEnd('"')
    $string=$string.TrimStart(' ')
    $string=$string.TrimEnd(' ') | Out-File $Path\Groups\GroupsListTemp.txt -Append
}
Remove-Item $Path\Groups\GetGroupsAD.txt -Force
$InputFile = gc $Path\Groups\GroupsListTemp.txt
$OutputFile = "$Path\Groups\GroupsList.txt"
foreach ($line in $InputFile) 
{
    ReCode -f "windows-1251" -t "utf-8" $line
}
Remove-Item $Path\Groups\GroupsListTemp.txt -Force
 
#Создание файлов со списком пользователей для каждой группы
$GroupName = @(Get-Content $Path\Groups\GroupsList.txt)
Foreach ($Group in $GroupName)
{
    Get-ADGroupMember $Group -recursive | ft SamAccountName | out-file "$Path\UsersTemp\$Group.txt" -Append
    (get-content "$Path\UsersTemp\$Group.txt")  -notmatch "Name" | where {$_ -ne ""} | where {$_ -ne "--"} | Where-Object {$_ -notmatch '-'} | out-file "$Path\UsersTemp\$Group.txt"
    $File=@(Get-Content $Path\UsersTemp\$Group.txt)
    foreach ($File1 in $File) 
    {
        $string=$File1.TrimStart('"')
        $string=$string.TrimEnd('"')
        $string=$string.TrimStart(' ')
        $string=$String.TrimEnd(' ') | Out-File "$Path\UsersTemp\$Group" -Append
    }
    $InputFile = gc $Path\UsersTemp\$Group
    $OutputFile = "$Path\Users\$Group"
    foreach ($line in $InputFile) 
    {
        ReCode -f "windows-1251" -t "utf-8" $line
    }
}
Remove-Item "$Path\UsersTemp\" -Recurse -Force
Remove-Item "$Path\Groups" -Recurse -Force



5. Скрипт на Bash для создания списков рассылки


Оговорюсь по поводу копирования файлов-скриптов, созданных под Windows
В прошлой статье был описан метод форматирования файлов с помощью команды cat, которая, будучи запущенная с определенным ключом, убирает все лишние нечитаемые символы. Ссылка на статью в конце статьи.

Скрипт Bash
#!/bin/bash
#Определение переменных
#Путь к рабочему каталогу
Path="/mnt/ZM/ZimbraDL"
#имя домена Zimbra
Domain="zimbramail.home.local"
#путь к командлету zmprov
zmprov="/opt/zimbra/bin/zmprov"
#путь к лог-файлу
log="/mnt/ZM/DLlog.txt"
#путь ко временному файлу со списком групп
DLnames="/mnt/ZM/DLnames"
#путь ко временному файлу со списком пользователей
UserNames="/mnt/ZM/Usernames"
#конец блока переменных

echo "Запись списка групп..."
ls $Path/Users > $DLnames
if [ $? -eq 0 ]; then
	echo -n "$(tput hpa $(tput cols))$(tput cub 6) [OK]"
	echo
	echo -en "ls directory for Groups correct $(date +%T)\n" >> $log
else
	echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]"
	echo
	echo -en "ls directory for Groups INcorrect $(date +%T)\n" >> $log
fi
#Удаление списков рассылки
echo "Удаление обновляемых списков рассылки"
for DLname in $( cat $DLnames); do
	#Проверка существования списка рассылки
	echo "Проверка существования списка рассылки $DLname..."
	Result=$($zmprov gdl $DLname@$Domain)
	if [ $? -eq 0 ]; then
		echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]"
		echo
		echo -en "DL $DLname exist $(date +%T)\n" >> $log
		#Удаление списка рассылки
		echo -en "Start deleting DL for group $DLname $(date +%T)\n" >> $log
		echo "Удаление списка рассылки $DLname..."
		$zmprov ddl $DLname@$Domain
		if [ $? -eq 0 ]; then
			echo -n "$(tput hpa $(tput cols))$(tput cub 6) [OK]"
			echo
			echo -en "DL for group $DLname is deleted in $(date +%T)\n" >> $log
		else
			echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]"
			echo
			echo -en "DL for group $DLname is NOT deleted in $(date +%T)\n" >> $log
		fi
	else
		echo -n "$(tput hpa $(tput cols))$(tput cub 6)[FAIL]"
		echo
		echo -en "DL $DLname not exist! $(date +%T)\n" >> $log
	fi	
done
for DLname in $( cat $DLnames); do
	#Создание списка рассылки
	echo -en "Start create DL for group $DLname $(date +%T)\n" >> $log
	echo "Создание списка рассылки для группы AD $DLname..."
	$zmprov cdl $DLname@$Domain
	if [ $? -eq 0 ]; then
		echo -n "$(tput hpa $(tput cols))$(tput cub 6) [OK]"
		echo
		echo -en "DL for group $DLname is created in $(date +%T)\n" >> $log
	else
		echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]"
		echo
		echo -en "DL for group $DLname is NOT created in $(date +%T)\n" >> $log
	fi
	#Наполнение списка рассылки
	echo "Наполнение списка рассылки"
	for UserName in $( cat $Path/Users/$DLname); do
		echo "Проверка существования ящика для пользователя $UserName..."
		Result=$($zmprov gmi $UserName@$Domain)
		if [ $? -eq 0 ]; then
			echo -n "$(tput hpa $(tput cols))$(tput cub 6) [OK]"
			echo
			echo -en "MilBox for user $UserName exist $(date +%T)\n" >> $log
			echo "Добавление пользователя $UserName в список рассылки $DLname@$Domain..."
			$zmprov adlm $DLname@$Domain $UserName@$Domain
			if [ $? -eq 0 ]; then
				echo -n "$(tput hpa $(tput cols))$(tput cub 6) [OK]"
				echo
				echo -en "User $UserName added in $DLname@$Domain correctly in $(date +%T)\n" >> $log
			else
				echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]"
				echo
				echo -en "DL for group $DLname is NOT created in $(date +%T)\n" >> $log
			fi
		else
			echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]"
			echo
			echo -en "MilBox for user $UserName is NOT exist $(date +%T)\n" >> $log
		fi
	done
done
#Очистка временных файлов
echo "Очистка временных файлов"
echo "Очистка файла со списком групп..."
echo -n > $DLnames
if [ $? -eq 0 ]; then
	echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]"
	echo
	echo -en "File $DLnames was successfull cleared in $(date +%T)\n" >> $log
else
	echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]"
	echo
	echo -en "File $DLnames was NOT cleared in $(date +%T)\n" >> $log
fi
#Удаление директорий, содержащих структуру групп и пользователей
echo "Удаление рабочего каталога $Path для очистки свободного пространства..."
rm -rf $Path
if [ $? -eq 0 ]; then
	echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]"
	echo
	echo -en "Directory $Path was seccessfull deleted in $(date +%T)\n" >> $log
else
	echo -n "$(tput hpa $(tput cols))$(tput cub 6) [FAIL]"
	echo
	echo -en "Directory $Path was NOT deleted in $(date +%T)\n" >> $log
fi
#запись в лог-файл времени окончания обновления списков рассылки
echo -en "Job complete in $(date +%T)\n" >> $log
echo -en "____________________________________\n" >> $log


5.1. Как работает скрипт


  1. Записать в файл список групп
  2. Проверить существование списка рассылки в Zimbra, при существовании – удалить его
  3. Поочередно создать списки рассылки на основе списка групп, наполняя каждый из них пользователями (на экран выводится ID списка рассылки, это стандартный вывод командлета zmprov при создании DL). При этом проверяется существование почтовых ящиков пользователей в Zimbra, и если ящика не существует, то пользователь не будет добавлен в список рассылки. Можно, конечно, создать пользователю новый почтовый ящик и добавить его в список рассылки, но я исходит из того, что Zimbra autoprov работает в режиме Eager, и если пользователь не создался автоматически, то ему и нечего делать в системе
  4. Очистить временные файлы
  5. Удалить рабочую директорию

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


В целом, задача не сложная, проблема была лишь в передаче данных из PowerShell в Bash. Я довольно долго пытался найти инструмент для рекодирования текстовых файлов с выводом PoSh в удобоваримый для Bash вид. Результатом многодневных поисков стала функция:

Функция рекодирования
$InputFile = gc File1.txt
$OutputFile = "File2.txt"
$enc = [system.text.encoding]
function ReCode ( $f, $t, $line ) 
{
    $cp1          = $enc::getencoding( $f )
    $cp2          = $enc::getencoding( $t )
    $inputbytes   = $enc::convert( $cp1, $cp2, $cp2.getbytes( $line ))
    $outputstring = $cp2.getstring( $inputbytes )
    $outputstring | add-content $OutputFile
}
foreach ($line in $InputFile) 
{
    ReCode -f "windows-1251" -t "utf-8" $line
}


Может, кому-то будет полезно.

7. P.S.:


Это третья статья из серии «как я «Zimbra» внедрял». Первая, про внедрение, LDAP-авторизацию и автоматическое создание ящиков для пользователей AD, вот тут. Вторая, про настройку резервного копирования и восстановления Zimbra целиком и отдельными ящиками – тут.

8. P.S.S.:


Есть более простой способ, описанный тут товарищем kiby75
Реклама
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее

Комментарии 6

    0
    $groups = Get-AdGroup -filter * -SearchBase "OU=ZimbraDL,DC=home,DC=local"
    foreach ($group in $groups) {$groupname = $group.name; get-adgroupmember $groupname | select samaccountname | export-csv -LiteralPath $path\$groupname.csv -Encoding utf8 -Delimiter ';' -NoTypeInformation -Force}

    С парсингом csv под bash проблем быть не должно
      0
      При использовании csv проблема не рашается. При парсинге башем все так же либо чистится файл, либо остаются «непечатные символы». Я уже пробовал этот вариант.
        0
        У меня заработала только вот такая конструкция:
        $file = gc file.txt
        $enc = [system.text.encoding]
        function ReCode ( $f, $t, $string ) {
            $cp1          = $enc::getencoding( $f )
            $cp2          = $enc::getencoding( $t )
            $inputbytes   = $enc::convert( $cp1, $cp2, $cp2.getbytes( $string ))
            $outputstring = $cp2.getstring( $inputbytes )
            $outputstring | add-content file1.txt   
        }
        foreach ($string in $file) {
            ReCode-f "windows-1251" -t "utf-8" $string
        }

        И сегодня-завтра переделаю статью + прикручу возможность обновления списков рассылки по одному, чтобы все разом не лопатить.
          0
          Мне кажется что PowerShell и передача списка через шару это лишнее. Почему нельзя сразу из линукс конектится в домен и получать список групп и членов группы? Bash не всесилен, но Python и Perl вполне могут в ad ходить за инфой.
            0
            Я не владею Питоном или Перлом. Да, можно и так сделать, конечно, и это будет правильнее даже. Но я не умею. А изучать языки ради 2х скриптов — дело такое…
            Если Вы можете — сделайте, напишите об этом пост. Ну или я могу добавить ваши скрипты с вашим копирайтом в эту статью.
        0
        немного переделал скрипт, исключил повершел (заменил на идущий с Zimbra ldapsearch). Так же исключил удаление и пересоздание групп рассылки.
        пояснения:
        в функции searchgroupsAD эта часть необходима, так как у меня в AD все группы рассылки начинаются с mail_имяГруппыРассылки поэтому mail_ убираем
        tr '_' ' ' | 
        awk '{print $2}' |
        


        скрипт:
        скрипт:
        #!/bin/bash
        #
        #1. Определение переменных
        #
        #1.1 Общие переменные
        #Путь к рабочему каталогу
        path="/mnt/zimbra/list-sync"
        #Временная метка
        timestamp=`date +%F-%H-%M`
        #путь к временным файлам
        tmp_dir=$path/tmp
        #путь к файлам логов
        log_dir=$path/log
        #имя лог-файла
        log=$log_dir/grouplog_$timestamp.txt
        #путь ко временному файлу со списком групп
        glname=$tmp_dir/glname
        #Путь к файлу со списком команд на пакетное выполнение утилитой zmprov
        zmcmdfile=$tmp_dir/zmcmdfile
        #путь ко временным файлам со списком пользователей в группах рассылки
        groupuser=$tmp_dir/group
        #отправка почты
        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"
        #OU поиска групп рассылки
        groupdn="OU=mailgroup,DC=test,DC=local"
        #Пользователь и пароль для доступа к AD по LDAP
        binddn="CN=zimbra,CN=Users,DC=test,DC=local"
        bindpw="qwe123" #user password 
        #какие поля данных ищем (логин, почту и поле с несовпадающей с логином почтой для алиаса и подписи)
        fields="sAMAccountName mail extensionAttribute1"
        #конец блока переменных
        
        #Начинаем обработку
        
        #Функции обработки
        #Запись ошибки в лог
        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 searchgroupsAD()
        {
        	# Убираем первую часть разделителя группы
        	echo "Запись списка групп рассылки из AD..." >> $log
        	$ldapsearch -x -o ldif-wrap=no -H $ldap_server -D $binddn -w $bindpw -b $groupdn sAMAccountName | 
        	grep sAMAccountName | 
        	egrep -v '^#|^$' | 
        	awk '{print $2}' |
        	tr '_' ' ' | 
        	awk '{print $2}' |
        	sort > $glname.ad
        	echo "Found (Найдено) "`cat $glname.ad | wc -l`" Group in AD (групп в AD)" >> $log
        }
        
        #Запись в файл списка групп рассылки из zimbra 
        function searchgroupzimbra()
        {
        	echo "Запись списка групп рассылки из zimbra..." >> $log
        	$zmprov gadl $domain |  
        	sed 's/@.*//g' | 
        	sort > $glname.zim
        	echo "Found (Найдено) "`cat $glname.zim | wc -l`" Group in Zimbra (групп в Zimbra)" >> $log
        }
        
        #Заполнение файла списка группы пользователями AD
        function user-group-AD()
        {
        	#Список пользователей AD
        	$ldapsearch -x -o ldif-wrap=no -H $ldap_server -D $binddn -w $bindpw -b $groupdn  "(sAMAccountName=mail_$1)" member | 
        	grep member | 
        	egrep -v '^#|^$' | 
        	awk '{print $2}' | 
        	sed -r 's/CN=//' | 
        	awk '{split ($0, a, ","); print a[1]}' | 
        	sort > $groupuser/$1.ad	
        	echo "Found (Найдено) "`cat $groupuser/$1.ad | wc -l`" users AD in group $1 (пользователей AD в группе $1)" >> $log
        }
        
        #Заполнение файла списка группы пользователями Zimbra
        function user-group-zim()
        {
        	#Создание списков пользователей Zimbra
        	$zmprov gdlm $1@$domain | 
        	sed 1,3d | 
        	sed 's/@.*//g' | 
        	sort > $groupuser/$1.zim
        	echo "Found (Найдено) "`cat $groupuser/$1.zim | wc -l`" users Zimbra in group $1 (пользователей Zimbra в группе $1)" >> $log
        	
        }
        
        function diff-user()
        {
        	diff -u -i $groupuser/$1.zim $groupuser/$1.ad | sed 1,3d > $groupuser/$1.diff
        	#ifdif=`cat $groupuser/$1.diff`
        	#проверяем, что файл не пустой
        	if [ -s $groupuser/$1.diff ];
        	then
        		for i in $( grep -v @ $groupuser/$1.diff );
        		do
        			#Проверяем какое действие - удаление или добавление
        			cha=`echo $i | cut -c -1`
        			#удаление из списка рассылки
        			if [ "$cha" == "-" ];
        			then 
        				deluser=`echo $i | cut -c 2-`
        				echo "rdlm $1@$domain $deluser@$domain" >> $zmcmdfile
        				echo "Удаляем пользователя $deluser из списка $1" >> $log
        				echo "Пользователь $deluser удален из списка $1" >> $tmp_dir/send.txt
        			fi
        			#Добавление пользователя
        			if [ "$cha" == "+" ];
        			then 
        				adduser=`echo $i | cut -c 2-`
        				echo "adlm $1@$domain $adduser@$domain" >> $zmcmdfile
        				echo "Добавляем пользователя $adduser в список $1" >> $log
        				echo "Пользователь $adduser добавлен в список $1" >> $tmp_dir/send.txt
        			fi
        		done
        	fi
        }
        
        #добавление в пакетный файл команды создания списка рассылок
        function addcmdlist()
        {
        	# Добавляем в файл команды на создание новых списков рассылки в zimbra
        	# проверяем наличие первой строки
        	iflist=`grep ^+ $glname.diff | sed '1!d' | cut -c 2-`
        	#проверяем, что файл не пустой
        	if  [ -n $iflist ];
        	then
        		for group in $(grep ^+ $glname.diff | cut -c 2-);
        		do
        			echo "cdl "$group@$domain >> $zmcmdfile 
        			echo "Добавляем списк рассылки $group" >> $log
        			echo "Список рассылки $group добавлен" >> $tmp_dir/send.txt
        		done
        	fi
        }
        
        #функция удаления группы рассылки (см addcmdlist с заменой в цикле grep "+" на grep "-"
        #и строки "cdl "$group@$domain  на "rdl "$group@$domain 
        #d нашем случае только отправка уведомления админу
        function delcmdlist()
        {
        	# Добавляем в файл команды на создание новых списков рассылки в zimbra
        	iflist=`grep ^- $glname.diff | cut -c 2-`
        	#проверяем, что файл не пустой
        	if  [ -n $iflist ];
        	then
        		for group in $(grep ^- $glname.diff | cut -c 2-);
        		do
        			# Если надо удалить группу, то раскоментируем строку ниже, я просто посылаю уведомление администратору
        			#echo "cdl "$group@$domain >> $zmcmdfile 
        			echo "Удаляем списк рассылки $group" >> $log
        			echo "Список рассылки $group помечен на удаление!!! проверьте и удалите самостоятельно!" >> $tmp_dir/send.txt
        		done
        	fi
        }
        
        #Создание файлов с именами групп списков рассылки для синхронизации
        function filesgroup()
        {
        	#Выбираем только новые и существующие группы
        	# группы на удаление обрабатываем отдельно
        	for group in $( cat $glname.ad );
        	do
        		echo "Создание файла со списком пользователей группы "$group >> $log
        		#Очищаем или создаем списки группа-пользователь
        		:> $groupuser/$group.ad
        		:> $groupuser/$group.zim
        		:> $groupuser/$group.diff
        		user-group-AD $group
        		user-group-zim $group
        		diff-user $group
        		
        	done
        }
        
        
        #Выполнение скрипта
        #2.Проверка существования каталогов
        #Корневой каталог обработки
        if_path $path
        #Каталог временных файлов
        if_path $tmp_dir
        #Каталог лог-файла
        if_path $log_dir
        #Каталог со списком групп
        if_path $groupuser
        
        #Очищаем файл со списком команд на пакетное выполнение утилитой zmprov
        :> $zmcmdfile
        :> $tmp_dir/send.txt
        #3.Создаем список групп рассылки из AD 
        searchgroupsAD
        
        #4.Создаем список существующих в zimbra групп рассылки
        searchgroupzimbra
        
        #5.Сравниваем оба списка групп рассылки
        diff -u -i $glname.zim $glname.ad | sed 1,3d > $glname.diff
        
        #8. Создаем новые группы рассылки в zimbra
        addcmdlist
        delcmdlist
        
        #6. Создаем список пользователей в группах рассылки AD (новые и существующие)
        #7. Создаем список пользователей в существующих группах рассылки zimbra
        #9. Поочередно сравниваем пользователей в группах рассылки и создаем список на модификацию (добавление и удаление пользователей из групп рассылки zimbra)
        filesgroup
        
        
        $zmprov -f $zmcmdfile
        echo "Файл пакетного выполнения команд:" >> $log
        cat $zmcmdfile >> $log
        #Отправляем письмо с изменениями админу (если они есть)
        if [ -s $tmp_dir/send.txt ];
        then
        	$mutt  -s "Изменение списков рассылки на $timestamp" admins@test.ru -a $log < $tmp_dir/send.txt
        fi
        
        #Удаляем временные файлы и каталоги
        rm -R -f $tmp_dir
        


        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое