Скрипт sync_deps_for_users.py предназначен для синхронизации информации о департаментах пользователей между Active Directory (AD) и Yandex 360. Он извлекает данные о пользователях и их департаментах из AD через LDAP, сравнивает их с департаментами в Yandex 360 и обновляет данные в Yandex 360, если необходимо. Скрипт поддерживает режим "сухого прогона" (DRY_RUN) для тестирования без внесения изменений.
Ключевой особенностью работы этого скрипта является использование [иерархической адресной книги Exchange] (https://learn.microsoft.com/en-us/exchange/address-books/hierarchical-address-books/hierarchical-address-books) или её аналога (вложенных групп). В этом случае, имеется корневая группа, в которую вложены другие группы и т.д. Корневая группа представляет собой верхний уровень иерархии подразделений в организации Exchange, вложенные группы - иерархическую структуру подразделений внутри организации. Каждый пользватель в Active Directory может входить только в одну группу внутри данной иерархии.
Скрипт читает информацию о иерархии подразделений, начиная с корневой группы и воссоздаёт эту иерархию в виде иерархии подразделений в Яндекс 360. Плюс добавляет пользователей Яндекс 360 в соответствующие разделы иерархии. Если у группы в AD есть адрес электронной почты, то он присваивается соответствующему подразделению в Яндекс 360 и это подразделение можно использовать как группу при назначении прав, формированию списка пользователей канала/чата в Мессенджере или как список рассылки в Почте.
-
Чтение данных из Active Directory:
-
Подключается к AD через LDAP, используя параметры из файла
.env_ldap(хост, порт, учётная запись, базовый DN, фильтр поиска). -
Запрашивает атрибуты пользователей и групп (
distinguishedName,mail,displayName,department,objectCategory), соответствующих фильтру (например, членов группыYandex360) и членствую в корневой группе иерархической адресной книги. -
Формирует список с данными об ужле иерархии и членству пользователей в этом узле, например:
Global Address Book~hab@domain.ru Global Address Book;Division1~Division1@domain.ru Global Address Book;Division1|Иван Иванов;ivan@domain.ru Global Address Book;Division1;Team1~Team1@domain.ru Global Address Book;Division1;Team1|Пётр Петров;petr@domain.ruгде:
Global Address Book~hab@domain.ru,Global Address Book;Division1~Division1@domain.ruиGlobal Address Book;Division1;Team1~Team1@domain.ru- ноды в иерархии с описанием пути к ноде от корня и информацией об email адресе группы/ноды (разделитель;для пути к ноде и~между маршрутом к ноде и её email адресом).Global Address Book;Division1|Иван Иванов;ivan@domain.ruиGlobal Address Book;Division1;Team1|Пётр Петров;petr@domain.ru- информацию о членстве пользовалей в конкретной ноде (разделитель|между маршрутом к ноде и даными пользователя (displayName;email))
-
Сохраняет результаты в CSV-файл, если указан
OUT_FILE.
-
-
Получение данных из Yandex 360:
- Использует API Yandex 360 для получения списка департаментов (полный путь от корневого департамента) и пользователей.
- Формирует словарь департаментов
{id: полный_путь_к_департаменту}и словарь пользователей{alias: departmentId}.
-
Сравнение и синхронизация:
- Сравнивает список департаментов из AD с департаментами в Yandex 360.
- Добавляет новые департаменты из AD в Yandex 360 (если они отсутствуют), если
DRY_RUN=false. - Для каждого пользователя в Yandex 360 проверяет, совпадает ли его департамент с данными из AD:
- Если департамент отличается, обновляет
departmentIdпользователя в Yandex 360 через API (еслиDRY_RUN=false). - Если департамент в AD пустой, переводит пользователя в корневой департамент (
departmentId=1).
- Если департамент отличается, обновляет
- Проверяет псевдонимы (aliases) пользователей, если их основной email отсутствует в AD, и синхронизирует департаменты по псевдониму.
-
Логирование:
- Логирует операции в консоль (уровень INFO) и в файл
sync_deps.log(уровень DEBUG). - Ротация логов происходит при достижении 10 МБ, хранится до 20 резервных копий.
- Логирует операции в консоль (уровень INFO) и в файл
Скрипт использует переменные окружения, задаваемые в файле .env_ldap в каталоге скрипта или непосредственно в окружении:
| Имя параметра | Описание | Обязательный | Пример значения |
|---|---|---|---|
token |
OAuth-токен для аутентификации в API Yandex 360. | Да | y0_AgAAAA... |
orgId |
Идентификатор организации в Yandex 360 (целочисленный). | Да | 123456 |
LDAP_HOST |
Адрес контроллера домена (DNS-имя или IP). | Да | dc01.contoso.com |
LDAP_PORT |
TCP-порт LDAP (389 для LDAP, 3268 для глобального каталога). | Да | 3268 |
LDAP_USER |
Учётная запись для подключения к LDAP (формат: domain\user). |
Да | contoso\ldap_connector |
LDAP_PASSWORD |
Пароль учётной записи LDAP. | Да | password |
LDAP_BASE_DN |
Базовый DN для поиска пользователей в AD. | Да | OU=Office,DC=contoso,DC=com |
LDAP_SEARCH_FILTER |
Фильтр поиска пользователей в AD. | Да | (memberOf=CN=Yandex360,OU=Groups,OU=Office,DC=contoso,DC=com) |
ATTRIB_LIST |
Список атрибутов для извлечения из AD (через запятую). | Да | distinguishedName,mail,displayName,department,objectCategory |
OUT_FILE |
Имя файла для сохранения результатов LDAP-запроса (CSV). | Нет | ad_users.csv |
DRY_RUN |
Режим "сухого прогона" (true для имитации, false для изменений). |
Нет (по умолчанию false) |
true или false |
HAB_ROOT_GROUP |
distinguishedName корневой группы | Да | "CN=New Star Corp,OU=HAB,DC=domain,DC=ru" |
- Обязательные параметры: Все, кроме
OUT_FILEиDRY_RUN, должны быть заданы. При их отсутствии скрипт завершится с ошибкой. - LDAP_HOST: Для нескольких доменов в AD требуется DNS-имя и настройка DNS-разрешения. Для одного домена можно указать IP.
- ATTRIB_LIST: Должен включать как минимум
mail,department,distinguishedName,displayName,objectCategoryдля корректной работы. - DRY_RUN: Если
true, скрипт только логирует предполагаемые изменения без их применения. - Файл
.env_ldap: Пример:token=y0_AgAAAA... orgId=123456 LDAP_HOST=dc01.contoso.com LDAP_PORT=3268 LDAP_USER=contoso\ldap_connector LDAP_PASSWORD=password LDAP_BASE_DN=OU=Office,DC=contoso,DC=com LDAP_SEARCH_FILTER=(memberOf=CN=Yandex360,OU=Groups,OU=Office,DC=contoso,DC=com) ATTRIB_LIST=distinguishedName,mail,displayName,department,objectCategory OUT_FILE=ad_users.csv DRY_RUN=false HAB_ROOT_GROUP=CN=New Star Corp,OU=HAB,DC=domain,DC=ru
Создать OAuth токен для аутентификации в API Яндекс 360. Токен должен содержать необходимые права для выполения операций управления ресурсами в организации Яндекс 360. Документация - Создание приложения. Последовательность шагов для создания токена:
- заходим на https://oauth.yandex.ru/client/new/. Аутентифицируемся от имени администратора организации Яндекс 360.
- Заполняем поля в форме создания приложения:
- Поле "Название вашего сервиса" - произвольное название.
- Включаем галочку "Веб сервисы"
- В поле
Redirect URLвводимhttps://oauth.yandex.ru/verification_code- В разделе "Почта для связи" указываем свой email.
- Добавляем разрешения для токена. Для этого в разделе "Доступ к данным" ищем и добавляем следующие разрешения:
| Имя разрешения | Что можно делать |
|---|---|
| directory:read_departments | читать информацию о подразделениях |
| directory:write_departments | изменять информацию о подразделениях |
| directory:read_users | читать информацию о пользователях |
| directory:write_users | изменять информацию о пользователях |
- нажимаем на кнопку "Создать приложение".
- Свойства созданного приложения отображаются в новом окне "Мои приложения". Ищем раздел с идентификатором созданного приложения и копируем строку из поля "ClientID":
- В текстовом редакторе созадем строку вида
https://oauth.yandex.ru/authorize?response_type=token&client_id=<идентификатор приложения>и вставляем в ней вместо<идентификатор приложения>скопированное значение ClientID из предыдущего пункта. Вставляем получившуюся ссылку в браузер и нажимаем "Enter". - В окне браузера появляется запрос на подтверждение прав токена. Подтверждение необходимо выполнить от учётной записи администратора организации (если это сделать от имени обычного пользователя, то токен не получит затребованных прав из-за отсутствия необходимых разрешений у данной пользовательской учётной записи). Нажимаем "Войти как" и получаем необходимый токен доступа.
Note
Полученный токен необходимо указать в файле .env_ldap в качестве значения параметра token
Для этого необходимо зайти в консоль администрирования и в левом нижнем углу интерфейса будет необходимый номер.
Note
ID организации необходимо указать в файле .env_ldap в качестве значения параметра orgId
-
Установите Python: Требуется Python 3.7 или выше.
-
Установите зависимости: Скрипт требует библиотеки:
python-dotenv: Для загрузки переменных окружения.ldap3: Для работы с LDAP.requests: Для запросов к API Yandex 360 (предполагается, что используется вAPI360).
Установите их с помощью:
pip install python-dotenv ldap3 requests aiohttp
-
Настройте окружение:
- Создайте файл
.env_ldapв каталоге скрипта с параметрами (см. пример выше). - Убедитесь, что у вас есть действующий OAuth-токен для Yandex 360, ID организации и учётная запись LDAP с правами чтения AD.
- Создайте файл
-
Подготовка:
- Поместите скрипт
sync_deps_for_users.pyв рабочий каталог. - Создайте и заполните файл
.env_ldapили задайте переменные окружения. - Убедитесь, что файл
lib/y360_api/api_script.pyс классомAPI360доступен.
- Поместите скрипт
-
Запуск скрипта:
python sync_deps_for_users.py
Скрипт:
- Подключится к AD и Yandex 360.
- Сравнит департаменты и обновит данные в Yandex 360 (если
DRY_RUN=false). - Запишет результаты в лог
sync_deps.logи, если указанOUT_FILE, в CSV-файл.
-
Режим сухого прогона:
- Установите
DRY_RUN=trueв.env_ldapдля тестирования без изменений:export DRY_RUN=true python sync_deps_for_users.py
- Установите
- Консоль: Сообщения уровня INFO (например,
2023-10-01 12:00:00.123 INFO: Получен список пользователей AD: 50). - Файл: Сообщения уровня DEBUG записываются в
sync_deps.log, ротация при 10 МБ (20 копий). - Формат:
%(asctime)s.%(msecs)03d %(levelname)s:\t%(message)sс датойГГГГ-ММ-ДД ЧЧ:ММ:СС.
- LDAP-ошибки: Ошибки подключения или поиска логируются, скрипт завершается.
- API-ошибки: Предполагается, что
API360обрабатывает ошибки; общие исключения логируются. - Пустые списки: Если списки пользователей или департаментов пусты, скрипт завершается с соответствующим сообщением.
- Отсутствующие пользователи: Пользователи Yandex 360, отсутствующие в AD, проверяются по псевдонимам.
Для работы скрипта ему необходимо передать данные об имени входа пользователя в Active Directory и пароле пользователя. Эти данные используются при подключении к LDAP протоколу и получению необходимых данных. С точки зрения безопасности использовать в открытом виде логин и пароль пользователя не является хорошоей идеей. Однако специфика работы Pythob скрипта такова, что избежать такой операции не представляется возможным:
- пароль не может быть представлен в виде хэша;
- скрытие пароля в виде строки обратного шифрования не повышает защиту от раскрытия пароля, т.к. одна строка в коде скрипта позволит вывести расшифрованный пароль а консоль работы скрипта. Для повышения безопасности решения можно рекомендовать два механизма:
- передать пароль перед запуском скрипта в виде значения переменной окружения (Environment Variables), при этом удалив соответствующий конфигурационный параметр из конфигурационного файла
.ldap_env. В Windows значение переменной можно задать командой:
set LDAP_PASSWORD=password
В Linux это будет команда:
export LDAP_PASSWORD=password
Дополнительно к передачи пароля в виде переменой среды рекомендуется выделить для работы скрипта специальную учётную запись, для которой установить ограничения на подключение к ресурсам в AD. Для этого в групповой политике домена указать такие ограничения:
Это позволит существенно сократить возможности по эксплуататции данных учётной записи.
- Требуется модуль
API360изlib/y360_api/api_script.py(не предоставлен в коде). - Поддерживаются только пользователи с заполненным
mailв AD. - Поиск по псевдонимам ограничен доменом основного email.




