Когда возникла задача синхронизации списков рассылки Zimbra с группами безопасности в AD, не зная с какой стороны подойти к решению задачи, я пошёл в Google, который выдал мне ссылку на статью на Хабре, в которой файл формировался на одном сервере, потом складывался на шару, потом парсился на другом сервере. После некоторых дополнительных поисков я пришёл к единственному скрипту на python, запускающегося по расписанию на сервере с Zimbra.
Перед тем, как описывать работу скрипта нужно описать окружение в котором он будет работать.
Сервер Zimbra использует для формирования Глобального списка адресов специально созданный OU "Простые пользователи", в котором находятся все учётные записи пользователей, сделано это для того, чтобы исключить из списка адресов возможные сервисные и администраторские учётные записи. Там же есть вложенный OU "Группы рассылки" содержащий группы, соответствующие группам рассылки, который мы и будем использовать для синхронизации.
Для синхронизации списка адресов пользователей в настройках GAL и для работы скрипта используется непривилегированный пользователь ldap_sync. Чтобы у него не было проблем с чтением данных, в настройках безопасности у групп и пользователей должно быть разрешение на чтение для пользователей прошедших проверку.
Для работы скрипта кроме самого python необходимо установить с помощью pip пакеты pyldap и pyyml.
Перед тем, как описывать работу скрипта нужно описать окружение в котором он будет работать.
Сервер Zimbra использует для формирования Глобального списка адресов специально созданный OU "Простые пользователи", в котором находятся все учётные записи пользователей, сделано это для того, чтобы исключить из списка адресов возможные сервисные и администраторские учётные записи. Там же есть вложенный OU "Группы рассылки" содержащий группы, соответствующие группам рассылки, который мы и будем использовать для синхронизации.
Для синхронизации списка адресов пользователей в настройках GAL и для работы скрипта используется непривилегированный пользователь ldap_sync. Чтобы у него не было проблем с чтением данных, в настройках безопасности у групп и пользователей должно быть разрешение на чтение для пользователей прошедших проверку.
Для работы скрипта кроме самого python необходимо установить с помощью pip пакеты pyldap и pyyml.
# Для Ubuntu
apt install libsasl2-dev python-dev libldap2-dev libssl-dev
apt install python-pip
pip install pyldap pyyml
# Для CentOS
yum install python-devel openldap-devel
yum groupinstall 'development tools'
pip install pyldap pyyml
Все приготовления выполнены, приступаем к созданию скрипта и сопутствующих файлов, содержащих сопоставление списков рассылки с группами в AD и аутентификационные данные пользователя, чтобы не хранить их прямо в скрипте.
Начнём с самого скрипта. Он будет проверять соответствие списка членов группы в AD c адресатами в списке рассылки Zimbra. Если пользователь есть в группе AD, но его адреса нет в списке рассылки, то он будет добавлен в список, если пользователя в группе нет, а адрес в списке рассылки есть, то адрес будет удалён из списка.
mkdir /scripts touch /scripts/zimbra_dl_sync.pyТ.к. python очень чувствителен к разметке, то нужно обратить внимание, чтобы в скрипте не было лишних пробелов и знаков табуляции в начале строки.
#!/usr/bin/python
# coding=UTF-8
lists_file = '/scripts/conf/lists.txt'
# file with config settings
conf_file = '/scripts/conf/cred.yml'
# base SCOPE
scope = 'DC=oldfag,DC=ru'
# search domain
domain = 'oldfag.ru'
# AD server
ldapserver = 'dc01'
# connection port
port = '389'
# users domain on zimbra
emaildomain = 'oldfag.ru'
# AD bind account domain
ldapbinddomain = 'oldfag'
# path to zmprov
pathtozmprov = '/opt/zimbra/bin/zmprov'
#--------------------------------------------------------------------------------------------------
import yaml, ldap, string, os, sys
# import credentials
conf = yaml.load(open(conf_file), Loader=yaml.BaseLoader)
ldapbind = conf['ldap']['user']
ldappassword = conf['ldap']['pass']
# connect to AD
ad=ldap.initialize('ldap://' + ldapserver + '.' + domain + ':' + port)
ad.protocol_version = ldap.VERSION3
ad.set_option(ldap.OPT_REFERRALS, 0)
ad.simple_bind_s(ldapbinddomain + '\\' + ldapbind, ldappassword)
# upload AD groups and Zimbra distribution lists
lists = {}
with open(lists_file, 'r') as lf:
for line in lf:
values = line.split(':')
lists[values[0]] = values[1].rstrip('\n')
for list, group in lists.items():
zml = os.popen(pathtozmprov + ' gdlm ' + list + '@' + emaildomain + ' | egrep -v "^$" | grep -v members | grep -v "#"')
member_list = []
res = []
res2 = []
member_list = zml.read().splitlines()
try:
res = ad.search_s(scope, ldap.SCOPE_SUBTREE, '(memberOf=CN='+group+',OU=Группы рассылок,OU=Простые пользователи,DC=oldfag,DC=ru)', ['mail'])
# check if AD group members are in zimbra distribution list
for rec in res:
# skip referal records if they exist
if rec[0]:
for key, value in rec[1].items():
e_mail = str(value).split("'")[1].lower()
# if they are not, then add them
if e_mail not in member_list:
os.system(pathtozmprov + ' adlm %s@%s %s' % (list,emaildomain,e_mail))
res2.append(e_mail)
# check if all distribution list member are in the AD group
for member in member_list:
e_mail = member.rstrip('\n')
# if they are not, then delete them
if e_mail not in res2:
os.system(pathtozmprov +' rdlm %s@%s %s' % (list,emaildomain,e_mail))
except ldap.LDAPError as error_message:
print(error_message)
ad.unbind_s()
Теперь что касается файла с сопоставлением групп и списков рассылки
mkdir /scripts/conf touch /scripts/conf/lists.txtОн содержит адреса групп рассылки Zimbra и имена групп безопасности в AD в виде
<адрес группы рассылки 1>:<имя группы в AD 1> <адрес группы рассылки 2>:<имя группы в AD 2>Так, для списка рассылки all@oldfag.ru, которому соответствует группа Все пользователи, строка в этом файле будет выглядеть вот так
all:Все пользователиПоследний файл, который нужен для работы скрипта - cred.yml, он содержит имя пользователя и пароль, от имени которого скрипт будет обращаться к AD за списком пользователей в группах.
touch /scripts/conf/cred.yml chmod 600 /scripts/conf/cred.ymlДля файла изменены разрешения, чтобы хотя бы создать видимость безопасности.
ldap:
user: ldap_sync
pass: 'userpassword'
Последнее, что осталось - добавить строку в /etc/crontab.
30 * * * * root /bin/python /scripts/zimbra_dl_sync.pyТочный путь к python можно узнать выполнив команду
which python
Для корректного отображения списка рассылки при создании нового письма в настройках GAL на сервере нужно выбрать только внешний источник адресного списка, а для всех локальных списков рассылки убедиться в том, что снята галка "Скрыть в GAL" во вкладке Свойства.
Добрый день
ОтветитьУдалитьПробовал данный метод но безуспешно(
Можете конкретнее показать какие значения нужно изменить в скрипте для его коректной работы?
Также можно ли организовать вывод какого нибудь лога для данного скрипта?
Зарание спасибо.
Чтобы всё работало нужно в самом скрипте указать ваши значения переменных, которые описаны до строки
Удалить#---------------------------------------
т.е. пути к конфигурационным файлам, имя контроллера домена, имена домена AD и почтового домена, а так же область для запроса к ldap.
и фильтр для поиска групп рассылки в строке
res = ad.search_s(scope, ldap.SCOPE_SUBTREE, '(memberOf=CN='+group+',OU=Группы рассылок,OU=Простые пользователи,DC=oldfag,DC=ru)', ['mail'])
В файле cred.yml указать логин и пароль пользователя для подключения к AD.
Для самого базового понимания, что происходит не так, можно попробовать запустить скрипт из консоли и посмотреть вывод.
Для ведения лога есть очень удобный модуль для python - logger.