Ни для кого не секрет, что современная IT-инфраструктура становится все сложнее и больше. Все больше систем автоматизации, накопления, обработки информации появляется в организациях. Помимо этого, каждая из систем развивается и становится сложнее, что требует больших усилий при их администрировании. Минимальным на предприятии я считаю должны быть:
Думаю, каждый администратор DIRECTUM или Active Directory, который хоть раз вручную проводил синхронизацию штатного расписания в системе, поймет меня. Когда отдел кадров не сообщает об изменениях в штатном расписании, переводе сотрудника на другую должность или перемещении сотрудника в другой отдел, а потом разом приходится вносить очень много изменений в DIRECTUM, то это отнимает очень много времени. В организации с численностью 50 человек это уже может стать камнем преткновения. Лично я поддерживаю мнение о том, что лень – двигатель прогресса, поэтому все, что можно автоматизировать, надо автоматизировать!
Классическая схема передачи сведений о сотруднике между системами выглядит примерно так:
Такая схема используется очень часто, так как именно в системе учета находятся самая актуальная информация, которая потом передается в Active Directory, откуда уже многие другие программы получают информацию.
В данной статье будет рассматриваться немного модифицированный вариант схемы, когда не вся информация может быть получена с кадровой системы учета:
Такой вариант обусловлен тем, что в DIRECTUM могут быть более полные данные о сотруднике, чем в системе учета или Active Directory. Конечно же, актуальная кадровая информация хранится в системе учета, но там может хранится на много меньше данных о сотруднике, чем в DIRECTUM. Active Directory может выступать как средство контроля доступа, но не содержать актуальной информации о пользователях.
Рассмотрим блоки схемы подробнее:
В стандартной поставке DIRECTUM есть возможность синхронизировать данные по пользователям из Active Directory в DIRECTUM, но нет возможности синхронизировать данные в обратную сторону. Я решил устранить данный пробел и реализовал обратную синхронизацию.
Расскажу об основных сложностях, с которыми пришлось столкнуться.
Самый распространённый вариант — это использование протокола LDAP, однако IS-Builder не умеет работать с LDAP-объектами напрямую. В данной ситуации может выручить ADODB.Connection.
DomenAD = 'test.local' // Домен или контроллер домена AD
DomenADPatch = 'OU=Moscow,DC=test,DC=local' // Путь внутри домена до корневого элемента
Connection = CreateObject('ADODB.Connection') // Получим объект для работы
Connection.Provider = 'ADsDSOObject' // Укажем провайдера для работы с LDAP
Connection.Open('ADs Provider') // Откроем соединение
Command = CreateObject('ADODB.Command') // Объявим объект для выполнения запроса.
// В качестве результата вернется объект RecordSet
Command.ActiveConnection = Connection // Передадим настроенное соединение
RecordSet = CreateObject('ADODB.Recordset') // Получим объект в котором будет
// храниться результат запроса
// Составим запрос в LDAP каталог, указав получаемые поля
Sql = "select
DisplayName,
sAMAccountName,
...
from
'LDAP://" & DomenAD & "/" & DomenADPatch & "'
where
objectCategory = 'Person' and objectClass = 'user'
order by name"
Command.CommandText = Sql // Передадим запрос для выполнения
RecordSet = Command.Execute // Выполним запрос и запишем результат
// в объект RecordSet
Один из плюсов такого варианта — это получение данных подобно SQL-запросу, где достаточно указать получаемые поля из схемы. Однако, данный поставщик предоставляет каталог LDAP только на чтение, что накладывает свои ограничения.
С первого взгляда ничего сложного тут нет, IUser.Name соответствует логину в Active Directory, но это не всегда так. Пользователь может изменить фамилию, имя и т.д., что может заставить администраторов Active Directory изменить ему имя входа в каталоге. Имя входа в DIRECTUM можно перегенерировать, однако, получить объект IUser с помощью ServiceFactory.GetUserByName по новому имени не получится. Для решения такой ситуации нужно проверить компоненту Пользователи на наличие данного логина и получить объект IUser сотрудника на основе данных поля Имя.
Пример определения:
// Получим компоненту Пользователи
URef = References.SYSREF_USERS.GetComponent
// Установим фильтр по реквизиту Логин
URef.Filter = '[UserLogin] = "' & RecordSet.Fields('sAMAccountName').Value & '"'
// Включим фильтр
URef.Filtered = true
// Откроем отфильтрованный справочник
URef.Open
if URef.RecordCount == 1
try
// Попробуем получить IUser
IUser = ServiceFactory.GetUserByName(URef.SYSREQ_CODE)
except
IUser = null
endexcept
endif
// Выключим фильтр
URef.Filtered = false
URef.Close
// Уничтожаем объект
URef = nil
Еще один момент который стоит учесть: у пользователя может быть несколько записей справочника Работники. Как тут поступать надо решать в каждом конкретном случае.
Основная сложность при обработке фотографий возникла из-за разных требований к фотографиям, в DIRECTUM и системах, которые получают фотографии из Active Directory. В самом Active Directory максимальный размер значения атрибута thumbnailPhoto пользователя, в котором хранится загружаемая фотография, составляет 100Кб.
Для изменения изображений можно использовать стандартный объект Windows Image Acquisition (WIA), который позволяет изменять изображения на лету, не устанавливая стороннего программного обеспечения.
// Получаем объект для управления фильтрами изображений
ImageProcess = CreateObject("WIA.ImageProcess")
// Получаем контейнер для работы с изображениями
ImageFile = CreateObject('WIA.ImageFile')
// Находим фильтр Scale, который позволяет управлять масштабом изображений
Filter = ImageProcess.FilterInfos("Scale").FilterID
// Добавляем фильтр для возможности работы с ним
ImageProcess.Filters.Add(Filter)
// Указываем размеры изображения, которое нам надо получить.
// Размеры указываются в пикселях
ImageProcess.Filters(1).Properties("MaximumWidth").Value = 250
ImageProcess.Filters(1).Properties("MaximumHeight").Value = 250
// Применим фильтр к изображению
ImageFile = ImageProcess.Apply(ImageFile)
// Сохраним изображение в файл
ImageFile.SaveFile(ImagesFullPath)
Такой вариант должен работать на рабочих станциях с Windows 10, а также Windows Server 2016, в остальных случаях требуется установка дополнительных компонентов системы: Возможности рабочего стола. При необходимости можно провести преобразование изображения в другой формат. Для этого можно использоваться фильтр Convert.
Преобразование и изменение размера изображения не самая быстрая операция. Поэтому вариант обновления фотографий в Active Directory надо рассматривать индивидуально. При маленьком количестве фотографий или наличии достаточно хорошего канала связи между контроллерами домена, можно постоянно загружать фотографии в каталог, где они будут реплицироваться между контроллерами домена. Необходимо учесть, что при наличии медленного канала связи между контроллерами домена (или большого количества: фотографий, контроллеров домена) лучше будет выгружать фото из Active Directory и проводить сравнения, так как в момент занесения фото в Active Directory обновленный объект будет реплицироваться на все контроллеры, что может быть еще более длительной операцией.
Выше я уже упоминал, что IS-Builder не умеет работать с LDAP-объектами напрямую, поэтому встал вопрос поиска вариантов обновления информации в Active Directory. Решение оказалось очень простым, на помощь пришел VBScript.
В IS-Builder формируем скрипт, который в конце выполняем с помощью MSScriptControl.ScriptControl.
// Формируем скрипт, который будет выполняться
SCRIPT_TEXT = 'Set objUser = GetObject("LDAP://' & DomenAD & '/' & DistinguishedName & '")
objUser.PutEx 1, "jpegPhoto", vbNullString
objUser.PutEx 1, "thumbnailPhoto", vbNullString
objUser.SetInfo'
// Объявляем объект, для выполнения скрипта
Script = CreateObject('MSScriptControl.ScriptControl')
// Указываем язык скрипта, который будет выполняться
Script.Language = 'VBScript'
Script.Reset
Script.AddObject('AttList'; CreateList())
// Передаем скрипт для его выполнения
Script.AddCode(SCRIPT_TEXT)
// Не забываем очищать объект
Script = nil
Разберем более подробно.
С помощью функции GetObject() мы получаем объект LDAP. Дальнейшее обновление информации в объекте производится с помощью метода Put().
При записи данных в Active Directory стоит учесть, что пустая строка, переданная в качестве параметра в методе Put(), вызовет ошибку во время выполнения скрипта. Для очистки значения в Active Directory стоит использовать метод PutEx(), так как он обладает более гибкими настройками. В качестве первого параметра он принимает способ изменения информации в каталоге. Это могут быть:
Все изменения которые вносятся в объект с помощью методов Put() и PutEx() выполняются только на локальном компьютере. Для обновления заранее подготовленных данных непосредственно в Active Directory необходимо вызвать метод SetInfo(), который вносит изменения в саму службу.
Особенностью данного подхода является его асинхронность, поэтому при загрузке фотографий в Active Directory не стоит сразу их удалять, чтобы избежать ошибок и дать возможность объекту, корректно загрузить изображения в каталог.
Ниже приложен сценарий для примера, который проводит обновление данных в Active Directory выгружая информацию из DIRECTUM. Сценарий проводит обновление следующих реквизитов в Active Directory:
Список реквизитов может быть изменен (Полный список атрибутов объектов AD), в зависимости от потребностей организации.
Все операции по обновлению или изменению данных происходят после сопоставления пользователя Active Directory и пользователя DIRECTUM.
Пара слов о параметрах в сценарии на которые стоит обратить внимание:
Для полноценной работы синхронизации, необходимо добавить учетной записи Active Directory, от имени которой будет запускаться сценарий, права на обновление необходимых атрибутов в домене.
Данный сценарий приведен для примера и не служит окончательным решением! Автор настоятельно рекомендует использовать его для ознакомительных целей или после доработок под потребности организации.
Для создания пользователя в АД из Директум используем следующую функцию:
Создаёт в конкретном подразделении department. У нас синхронизированы подразделения между АД и Директум.
ADAddUserToGroup добавляет пользователя в группы/группу:
ADPodr это distinguishedName группы в АД.
А часто всплывает необходимость обратной синхронизации из Directum в AD? Интересно, нужен ли подобный функционал в коробке.
На самом деле такой функционал — это частные случаи, чем правило. Я в начале статьи рассказывал о том, что в DIRECTUM чаще данные попадают из AD, чем наоборот. Напомню, все зависит от того как именно выстроена ваша архитектура предприятия.
Авторизуйтесь, чтобы написать комментарий