Главная » Скрипты » Outlook и фотографии.

Outlook и фотографии.

Пару лет назад в блоге команды Exchange появился замечательный пост — http://blogs.technet.com/b/exchange/archive/2010/03/10/gal-photos-in-exchange-2010-and-outlook-2010.aspx . И действительно, сейчас использование фотографий стало фактически стандартом. Однако еще один интересный аспект – поддержка этих фотографий в актуальном виде. В частности, я недавно столкнулся с такой задачей.

Здесь будет небольшое лирическое отступлениеSmile.

Вообще, тема управления учетными записями сотрудников – давно уже стала очень насущной. Фактически, это отдельное направление IT, также как почта, СУБД, веб и т.д. Почитать подробнее можно тут — http://en.wikipedia.org/wiki/Identity_management

или, например, на русском – статья на хабре http://habrahabr.ru/post/123428/

Такие системы, как, например, Forefront Identity Manager (http://www.microsoft.com/en-us/server-cloud/forefront/identity-manager.aspx) позволяют полностью отслеживать весь жизненный цикл учетных записей, синхронизировать данные учетных записей, централизованно управлять различными системами авторизации и многое другое. Таким образом, одна из подзадач – централизованное управление учетными записями сотрудников, с которой я начинал эту заметку легко и штатно решается если в организации развернуто решение класса IDM. Однако, к сожалению, сейчас такие системы все еще редкость. Правда, оборотной стороной является тот факт, что подобные системы всегда сложны и без грамотного планирования и внедрения – скорее принесут вред, нежели пользу.

Собственно поэтому, мы решили сначала сделать небольшое самодельное решение, которое позволит уже сейчас выполнять базовые операции, такие как синхронизация фотографий, синхронизация данных сотрудников (должность, отдел, грейд и т.д.), управление членством в группах, а в дальнейшем уже подумать о внедрении готового IDM-решения.

В этой заметке, я как раз хотел бы рассказать о небольшой системе синхронизации фотографий.

Основной вопрос, этой задачи – в том, как идентифицировать сотрудника в AD. Как ни странно, это сложный и неоднозначный вопрос, если подойти к нему с точки зрения, например, HR. DN сотрудника или его SamAccountName для них будут, мягко говоря, неудобны. Удобным вариантом может быть ФИО, однако этот вариант неудобен для отдела IT, поскольку это очень плохой идентификатор личности в информационной системе. Как минимум он не уникален. Еще одним вариантом, который может быть удобен, как HR, так и IT, является табельный номер сотрудника. Собственно, этим путем мы и пошли. Если один раз заполнить табельный номер для всех сотрудников, а затем при создании учетных записей сразу его заносить наравне с другими учетными данными, то у каждой учетной записи всегда будет некий идентификатор, который сможет связать учетную запись в AD и запись о сотруднике в базе HR (например, в 1С).

Заполнить этот параметр у уже существующих учетных записей можно с помощью скрипта. Естественно, что скрипт обработает не всех, поскольку ему как раз приходится привязываться к ФИО, а в этом случае разночтения всегда были и будут, однако большую часть данных он все-таки обработает. Оставшиеся данные (у нас это было порядка 4-5 %) придется обработать вручную. С другой стороны, это хороший повод навести небольшой порядок в AD Smile.

Для данной задачи я написал такой небольшой скрипт — syncPN.ps1

Принцип его работы достаточно прост. В свое время мы запросили у ребят занимающихся 1С задачу по расписанию, которая делает выгрузку данных по сотрудникам из 1С. Данная выгрузка необходима для автоматической синхронизации данных сотрудников в AD, о которой я упоминал выше. Однако ее первое назначение – как раз сделать первичную синхронизацию и заполнить всем сотрудникам табельный номер, чтобы в дальнейшем можно было бы использовать его как связующее звено при дальнейшей синхронизации по расписанию. Выгрузка осуществляется в формате CSV. В том числе она содержит ФИО на английском и табельный номер, которые нам как раз необходимы. Соответственно, скрипт считывает файл выгрузки и дальше в цикле (я использую для этого foreach) перебирает все строчки. Сначала скрипт пытается найти пользователя по связке Имя-Фамилия (на английском), а затем, если не получилось, то по имени акаунта, сгенерированному на основе связки Имя-Фамилия. Такие, на первый взгляд, неоптимальные критерии вызваны тем фактом, что данные в 1C и AD могут отличаться. То есть транслитерация русских имен на английском могла осуществляться по-разному. В результате, например, в AD у сотрудника может быть имя Alexandr, а в 1С Aleksandr. Попытки использовать русские значения ФИО для поиска сотрудника, тоже не очень успешны, поскольку в случае с иностранными сотрудниками, проблема транслитерации возникает снова, только в обратном порядке. В результате, осуществив поиск сотрудников и, убедившись, что в результате найдено только по одной учетной записи (привет тёзкам и однофамильцам Smile ), скрипт пытается проставить значения табельного номера в дополнительное поле (мы для этого используем расширенный атрибут 15). Все это завернуто в многочисленные try-catch и снабжено выводом отладочной информации, чтобы при запуске можно было перенаправить вывод в лог файл и отследить все сделанные изменения.

После того, как всем сотрудникам занесен табельный номер в учетную запись можно приступать к синхронизации. Единственное, о чем не стоит забывать, так это задавать табельный номер для новых сотрудников, при создании. Тут удобным решением будет небольшое приложение (например, на vbs/hta или на PowerShell) для заведения сотрудников, которое позволяет сразу заполнять все необходимые поля (это особенно актуально, когда используется много дополнительных полей).

Синхронизация данных, пока еще в разработке, а вот синхронизация фотографий уже запущена.

Работает синхронизация фотографий по следующему принципу:

У отдела кадров на файловом ресурсе есть хранилище фотографий сотрудников. При появлении новой фотографии она добавляется туда. Все фотографии именуются по определенному принципу (имя содержит фамилию, имя и табельный номер). Раз в день запускается скрипт, который проверяет наличие новых фотографий или обновление существующих и, в случае обнаружения таковых, выполняет загрузку (и предварительную обработку фотографии), после чего формирует отчет и отправляет его на нужную группу рассылки.

Рассмотрим теперь сам скрипт.

Поскольку у нас файловый сервер – кластер, то необходимо вначале сделать проверку, на нужной ли ноде запускается скрипт (запуск настроен на всех трех нодах, но только на одной скрипт выполнится, поскольку только на ней активен нужный ресурс. это сделано для того, чтобы при переключении на другую ноду скрипт не перестал запускаться. для того, чтобы избежать разброса по разным нодам, сам скрипт хранится на сетевом ресурсе). Можно для этого воспользоваться соответствующим модулем PowerShell, но мне показалось, что проще будет просто проверить наличие подключенным нужного диска с помощью Test-Path. В данном случае, если все в порядке, то скрипт выполняется, в противном случае, выполнение прекращается.

Далее загружаются необходимые модули (в конце заметки будет ссылка на загрузку) и задаются переменные.

После этого, мы получаем список всех сотрудников в подразделении, у которых есть табельный номер (это отсекает служебные учетные записи).

$usersWithPN = Get-QADUser -IncludedProperties extensionAttribute15,thumbnailPhoto -SearchRoot $searchRoot | Where-Object {$_.extensionAttribute15 -ne $null}

Для того, чтобы у полученных объектов была необходимая информация, нужно воспользоваться параметром –IncludedProperties, поскольку по умолчанию расширенные атрибуты у объекта пользователя не выводятся.

Далее я использую цикл foreach, чтобы перебрать всех сотрудников, которые были получены с помощью предыдущего запроса.

Первым шагом необходимо проверить, что фотография есть:

$content = Get-ChildItem $photoDir | Where-Object {$_.Name -match $fname}

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

Дальше начинаются проверки. Если фотография существует (при этом в единственном экземпляре), то проверяется дата предыдущего ее изменения. Если дата изменения меньше чем граничное значение (переменная $delay), то производится попытка загрузки фотографии. В данном случае мы сначала уменьшаем фотографию (поскольку в требованиях к загружаемым фотографиям стоит размер не более 96х96, то это необходимая операция) с помощью командлетов из модуля Image (для этого приходится воспользоваться временным файлом), а затем полученное изображение считываем в переменную $photo (задав тип byte) и пытаемся поместить это значение в атрибут thumbnailPhoto учетной записи. Для логирования всех действий я создаю отдельные объекты, которые позволяют задать для каждого события уровень важности и сообщение. В данном случае, я в начале создал пустой массив $eventsArray=@() в который добавляются все такие события.

Пример добавления:

$message = «Предупреждение. У пользователя » + $user.LastName + » » + $user.FirstName + » (» + $pn + «) фотография обновлена.» # генерируем текст сообщения

$event = New-Object PSObject # создаем новый объект

$event | Add-Member -MemberType NoteProperty -Name «Severity» -Value 2 «# задаем важность события и добавляем его в объект события

$event | Add-Member -MemberType NoteProperty -Name «Message» -Value $message # добавляем в объект события сообщение

$eventsArray = $eventsArray + $event # добавляем в массив событий объект события

Remove-Item -Path «Variable:\event» # удаляем больше ненужный объект

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

В финале своей работы, скрипт формирует отчет на основе заданного вначале уровне логирования и отправляет его по почте:

$events = $eventsArray | Where-Object {$_.Severity -ge $displayEvents} | ConvertTo-Html
$msg.Subject = «AD Sync report.» + «Уровень логирования: » + $displayEvents
$msg.IsBodyHTML = $true
$msg.Body = $events
$smtp = new-object Net.Mail.SmtpClient($smtpServer,$SMTPPort)
$smtp.Send($msg)

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

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

Хороший пример отправки с авторизацией есть у Васи Гусева, вернее, даже две ссылки на его блог лучше посмотреть – раз и два.

Ну, вот собственно и все.

В примерах используются квестовские командлеты (лично мне они нравятся больше, чем родные, но вполне можно использовать для описанных задач и родные командлеты). Ссылка на загрузку командлетов от Quest — http://www.quest.com/powershell/activeroles-server.aspx

Также используется модуль Image для PowerShell ( http://archive.msdn.microsoft.com/PSImage/), который позволяет производить обработку изображений.

Реклама

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s