В организации отдел кадров часто ежедневно проводит приемы на работу, увольнения, смены должностей и переводы в смежные подразделения или организации в 1С: ЗУП. В результате этого, системным администраторам приходилось постоянно на эти события отвлекаться: создавать, блокировать или изменять доменные учетные записи Active Directory и почтовые аккаунты в Outlook. Т.е. у каждого сотрудника свой ПК и почтовый ящик.
Например, если прием на работу, то необходимо создание учетных записей в Active Directory и Outlook, а когда увольнение, блокировка уже существующих учетных записей в Active Directory и Outlook с целью безопасности данных.
Со временем, системные администраторы написали скрипты через Powershell, чтобы облегчить свою работу: они в готовый скрипт вписывали вручную нужные данные (например ФИО и должность сотрудника), но этого было недостаточно, т.к. до сотрудников ИТ всегда доходила информация поздно об изменении из отдела кадров. Да и все равно приходилось отвлекаться на эту рутинную работу, банально чтобы запустить скрипт.
Поэтому было принято решение этот процесс автоматизировать…
Изначально для решения этого вопроса, я хотел сделать все с помощью 1С, т.е. создать с нуля базу, через эту базу обращаться к 1С: ЗУП за кадровыми данными, а затем с помощью каких-то дополнительных компонент из 1С влиять на Active Directory и Outlook. Но к сожалению или к счастью, мне так и не удалось найти достаточно информации в интернете по теме того, как можно из 1С гарантированно и без ошибок подключиться к доменной сети, как там что-то изменить. Пробовал все, что мог найти в интернете, пытался вникнуть, как работать со всем этим программно, однако ничего не получалось, и я уже хотел было отложить решение этой задачи на будущее.
Но один из админов предложил сделать так: для работы с AD и Outlook из 1С запускать уже готовые написанные скрипты, которые у них были через Powershell. За неимением других вариантов, решили пойти именно таким путем.
Цель была следующая:
Сделать автоматическую, надежную и прозрачную систему с рабочим местом пользователя сотрудника ИТ, которая сама бы по необходимости работала с доменными учетными данными в Active directory и Outlook.
Шаг 1. Создание базы 1С с БСП
Базу назвали "Конфигурация для выгрузки в Active Directory и Outlook"
Шаг 2. Получение актуальных кадровых данных из 1С ЗУП
В базе 1С ЗУП уже был настроен веб-сервис, который при обращении к нему делал запрос к регистру сведений КадроваяИсторияСотрудников и выводил список в виде JS. Поэтому и новая база 1С как раз начала делать обращение к этому веб-сервису, особо ничего нового создавать не пришлось.
Рисунок 1 - Результат запроса с кадровыми данными из веб-сервиса 1С ЗУП
Шаг 3. Сохранение в «1С AD/Outlook» только изменений кадровых данных
Т.е. этот регистр сведений как предварительный буфер, отражает, что сотрудник уволился, или сменил должность. Т.е. хранит в себе именно изменение кадровых данных, которые потом пригодятся в будущем.
Рисунок 2 - Регистр сведений "Лог событий ЗУП"
Шаг 4. Создаем документы «Кадровое событие» для отправки в Active Directory и Outlook
Это уже "объект", с которой будет работать или регламент, или системный администратор.
Рисунок 3 - Документ "Кадровое событие ЗУП"
Рисунок 4 - Рабочее место пользователя базы со списком документов "Кадровое событие ЗУП"
На этом, в принципе, все.
Полностью в автоматический режим эту базу изначально не выставляли, т.к. лично у меня были опасения, что в случае ошибки могут массово заблокироваться учетные учетные данные в AD и тогда никто не сможет зайти в свой компьютер. Поэтому начинали внедрение маленькими шагами от ручного режима, в полностью автоматический.
В полуавтоматическом режиме на случай ошибок был сделан реквизит "Одобрено", который в значении истина только запускал регламенты. Т.е. системный администратор сначала должен был "одобрить" кадровое событие. Сейчас в полностью автоматическом режиме этот реквизит уже не нужен.
Рисунок 5 - Регламентные задания в базе 1С. Операции увольнения выведены в отдельный регламент т.к. это совершенно другой скрипт из PowerShell, а также регламент по увольнению запускается ночью, т.к. эта операция с блокировкой учетных данных не сильно срочная
Рисунок 6 - Настройки регламентов. Т.к. не все сотрудники работают за компьютером, была сделана настройка для ограничения работы регламентов в разрезе должностей.
Пример кода для создания учетной записи в Active Directory
&НаСервере
Функция ДобавитьВActiveDirectoryНаСервере(ОтобрИмя,НомерТел,Должность,Отдел,Подразделение,Подразделение1,Дубль, ДокументДляВыгрузки)
ФИО = СтрРазделить(ОтобрИмя," ",Ложь);
Фамилия = ФИО[0];
Имя = ФИО[1];
ИмяПольз = Транслит(НРег(ФИО[0]+Лев(ФИО[1], 1)+Лев(ФИО[2], 1)),Ложь);
//Если Дубль Тогда
// ИмяПольз = ИмяПольз+"1";
// ОтобрИмя = ОтобрИмя+"1";
//КонецЕсли;
КомандаАДО = Новый COMОбъект("ADODB.Command");
СоединениеАДО = Новый COMОбъект("ADODB.Connection");
СоединениеАДО.Provider = "ADSDSOObject";
СоединениеАДО.Open("Active Directory Provider");
КомандаАДО.ActiveConnection = СоединениеАДО;
//Авторизация в Домене
Пользователь=РегламентныеЗаданияКадровоеСобытиеЗУП.ПолучитьСписокСтрокУчётнаяЗапись();
Пароль=РегламентныеЗаданияКадровоеСобытиеЗУП.ПолучитьСписокСтрокПарольДомена();
ДСО=ПолучитьCOMОбъект("LDAP:");
//Создание OU
Если ЗначениеЗаполнено(ДокументДляВыгрузки.Служба) Тогда
Попытка
obj = ДСО.OpenDSObject("LDAP://dc1/DC=gor/DC=company/OU=Users_ORG/OU="+Отдел, Пользователь, Пароль, 1);
Исключение
obj = ДСО.OpenDSObject("LDAP://dc1/DC=gor/DC=company/OU=Users_ORG", Пользователь, Пароль, 1);
objClass = "organizationalUnit";
objRelativeName = "OU="+Отдел;
Prop1Name = "ou";
Prop1Value = Отдел;
newObject = obj.Create(objClass, objRelativeName);
newObject.Put(Prop1Name, Prop1Value);
newObject.SetInfo();
obj = ДСО.OpenDSObject("LDAP://dc1/DC=gor/DC=company/OU=Users_ORG/OU="+Отдел, Пользователь, Пароль, 1);
КонецПопытки;
КонецЕсли;
Если ЗначениеЗаполнено(ДокументДляВыгрузки.Подразделение1) Тогда
Попытка
obj = ДСО.OpenDSObject("LDAP://dc1/DC=gor/DC=company/OU=Users_ORG/OU="+Отдел+"/OU="+Подразделение, Пользователь, Пароль, 1);
Исключение
obj = ДСО.OpenDSObject("LDAP://dc1/DC=gor/DC=company/OU=Users_ORG/OU="+Отдел, Пользователь, Пароль, 1);
objClass = "organizationalUnit";
objRelativeName = "OU="+Подразделение;
Prop1Name = "ou";
Prop1Value = Подразделение;
newObject = obj.Create(objClass, objRelativeName);
newObject.Put(Prop1Name, Prop1Value);
newObject.SetInfo();
obj = ДСО.OpenDSObject("LDAP://dc1/DC=gor/DC=company/OU=Users_ORG/OU="+Отдел+"/OU="+Подразделение, Пользователь, Пароль, 1);
КонецПопытки;
КонецЕсли;
Если ЗначениеЗаполнено(ДокументДляВыгрузки.Подразделение2) Тогда
Попытка
obj = ДСО.OpenDSObject("LDAP://dc1/DC=gor/DC=company/OU=Users_ORG/OU="+Отдел+"/OU="+Подразделение+"/OU="+Подразделение1, Пользователь, Пароль, 1);
Исключение
obj = ДСО.OpenDSObject("LDAP://dc1/DC=gor/DC=company/OU=Users_ORG/OU="+Отдел+"/OU="+Подразделение, Пользователь, Пароль, 1);
objClass = "organizationalUnit";
objRelativeName = "OU="+Подразделение1;
Prop1Name = "ou";
Prop1Value = Подразделение1;
newObject = obj.Create(objClass, objRelativeName);
newObject.Put(Prop1Name, Prop1Value);
newObject.SetInfo();
obj = ДСО.OpenDSObject("LDAP://dc1/DC=gor/DC=company/OU=Users_ORG/OU="+Отдел+"/OU="+Подразделение+"/OU="+Подразделение1, Пользователь, Пароль, 1);
КонецПопытки;
КонецЕсли;
////////
objClass = "user";
objRelativeName = "CN="+ОтобрИмя;
newObject = obj.Create(objClass, objRelativeName);
newObject.userAccountControl = 544; //544 означает, что пользователь был создан без пароля, который необходимо установить при первом входе
newObject.sn = Фамилия;
newObject.givenName = Имя;
newObject.displayName = ОтобрИмя;
newObject.description = Должность;
newObject.title = Должность;
newObject.department = Отдел;
newObject.sAMAccountName = ИмяПольз;
newObject.userPrincipalName = ИмяПольз + "@company.gor";
newObject.mail = ИмяПольз+"@company.ru";
newObject.mobile = НомерТел;
newObject.SetInfo();
Пауза(15);
//Добавление пользователя в группу
Если ЗначениеЗаполнено(ДокументДляВыгрузки.Служба) Тогда
//создание папки на шаре
ВременныйФайлСкриптаPowerShell = ПолучитьИмяВременногоФайла("ps1");
ТекстСкриптаPowerShell = "foreach($obj in Get-ChildItem -Path \\company.gor\companyshare\All\) {
|$path = ""\\company.gor\companyshare\All\$obj\"+ДокументДляВыгрузки.Служба+"""
|If(!(test-path $path))
|{
|New-Item -Path ""\\company.gor\companyshare\All\$obj\"+ДокументДляВыгрузки.Служба+""" -ItemType Directory
|}
|}";
ЗаписьТекстаСкриптаPowerShell = Новый ТекстовыйДокумент;
ЗаписьТекстаСкриптаPowerShell.УстановитьТекст(ТекстСкриптаPowerShell);
ЗаписьТекстаСкриптаPowerShell.Записать(ВременныйФайлСкриптаPowerShell, КодировкаТекста.Системная);
ЗапуститьПриложение("powershell "+ВременныйФайлСкриптаPowerShell,,Ложь);
Если НЕ СуществованиеГруппы(ДокументДляВыгрузки.Служба) Тогда
СозданиеГруппыБезопасности(ДокументДляВыгрузки.Служба);
ДобавлениеЮзераВГруппу(ОтобрИмя,ДокументДляВыгрузки.Служба);
Иначе
ДобавлениеЮзераВГруппу(ОтобрИмя,ДокументДляВыгрузки.Служба);
КонецЕсли;
КонецЕсли;
Если ЗначениеЗаполнено(ДокументДляВыгрузки.Подразделение1) Тогда
//создание папки на шаре
ВременныйФайлСкриптаPowerShell = ПолучитьИмяВременногоФайла("ps1");
ТекстСкриптаPowerShell = "foreach($obj in Get-ChildItem -Path \\company.gor\companyshare\All\) {
|$path = ""\\company.gor\companyshare\All\$obj\"+ДокументДляВыгрузки.Служба+"\"+ДокументДляВыгрузки.Подразделение1+"""
|If(!(test-path $path))
|{
|New-Item -Path ""\\company.gor\companyshare\All\$obj\"+ДокументДляВыгрузки.Служба+"\"+ДокументДляВыгрузки.Подразделение1+""" -ItemType Directory
|}
|}";
ЗаписьТекстаСкриптаPowerShell = Новый ТекстовыйДокумент;
ЗаписьТекстаСкриптаPowerShell.УстановитьТекст(ТекстСкриптаPowerShell);
ЗаписьТекстаСкриптаPowerShell.Записать(ВременныйФайлСкриптаPowerShell, КодировкаТекста.Системная);
ЗапуститьПриложение("powershell "+ВременныйФайлСкриптаPowerShell,,Ложь);
Если НЕ СуществованиеГруппы(ДокументДляВыгрузки.Подразделение1) Тогда
СозданиеГруппыБезопасности(ДокументДляВыгрузки.Подразделение1);
ДобавлениеЮзераВГруппу(ОтобрИмя,ДокументДляВыгрузки.Подразделение1);
Иначе
ДобавлениеЮзераВГруппу(ОтобрИмя,ДокументДляВыгрузки.Подразделение1);
КонецЕсли;
КонецЕсли;
Если ЗначениеЗаполнено(ДокументДляВыгрузки.Подразделение2) Тогда
Если НЕ СуществованиеГруппы(ДокументДляВыгрузки.Подразделение2) Тогда
СозданиеГруппыБезопасности(ДокументДляВыгрузки.Подразделение2);
ДобавлениеЮзераВГруппу(ОтобрИмя,ДокументДляВыгрузки.Подразделение2);
Иначе
ДобавлениеЮзераВГруппу(ОтобрИмя,ДокументДляВыгрузки.Подразделение2);
КонецЕсли;
КонецЕсли;
СоединениеАДО.Close();
ДобавлениеЮзераВГруппу(ОтобрИмя,"all");
ОтправкаСообщения(НомерТел,ИмяПольз);
Если СтрНайти(Нрег(ДокументДляВыгрузки.Должность),"начальник")>0
или СтрНайти(Нрег(ДокументДляВыгрузки.Должность),"руководитель")>0
или СтрНайти(Нрег(ДокументДляВыгрузки.Должность),"мастер")>0
Тогда
ДобавлениеЮзераВГруппу(ОтобрИмя,"Руководители Компании");
КонецЕсли;
КонецФункции
Пример кода для создания учетной записи в Outlook
&НаСервере
Процедура ВыгрузитьСобытиеВOutlookНаСервере(ДокументДляВыгрузки)
ПарольДомена1 = РегламентныеЗаданияКадровоеСобытиеЗУП.ПолучитьСписокСтрокПарольДомена();
ПозицияСимвола = Найти(РегламентныеЗаданияКадровоеСобытиеЗУП.ПолучитьСписокСтрокУчётнаяЗапись(), "@");
СтрокаДоСимволаРазделителя = Лев(РегламентныеЗаданияКадровоеСобытиеЗУП.ПолучитьСписокСтрокУчётнаяЗапись(), ПозицияСимвола - 1);
Попытка
ФИО = СтрРазделить(ДокументДляВыгрузки.ФИО," ",Ложь);
ИмяПольз = Транслит(НРег(ФИО[0]+Лев(ФИО[1], 1)+Лев(ФИО[2], 1)),Ложь);
ВременныйФайлСкриптаPowerShell = ПолучитьИмяВременногоФайла("ps1");
ТекстСкриптаPowerShell = "Set-ExecutionPolicy RemoteSigned
|$PlainPassword = '"+ПарольДомена1+"'
|$SecurePassword = $PlainPassword | ConvertTo-SecureString -AsPlainText -Force
|$UserName = 'company.gor\"+СтрокаДоСимволаРазделителя+"'
|$UserCredential = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $SecurePassword
|$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://ex1.company.gor/PowerShell/ -Authentication Kerberos -Credential $UserCredential
|Import-PSSession $Session -DisableNameChecking
|$user = '"+ИмяПольз+"'
|Enable-Mailbox -Identity $user
|Set-CasMailbox -Identity $user -PopEnabled $false
|Set-Mailbox -Identity $user -IssueWarningQuota 500MB -ProhibitSendQuota 600MB -ProhibitSendReceiveQuota 600MB -UseDatabaseQuotaDefaults $false
|Remove-PSSession $Session";
ЗаписьТекстаСкриптаPowerShell = Новый ТекстовыйДокумент;
ЗаписьТекстаСкриптаPowerShell.УстановитьТекст(ТекстСкриптаPowerShell);
ЗаписьТекстаСкриптаPowerShell.Записать(ВременныйФайлСкриптаPowerShell, КодировкаТекста.Системная);
ЗапуститьПриложение("powershell "+ВременныйФайлСкриптаPowerShell,,Ложь);
Сообщить("Почта создана");
ДокументДляВыгрузкиОбъект = ДокументДляВыгрузки.ПолучитьОбъект();
ДокументДляВыгрузкиОбъект.ДатаВыгрузкиВOutlook = ТекущаяДата();
ДокументДляВыгрузкиОбъект.СтатусВыгрузкиВOutlook = "Успешно";
ДокументДляВыгрузкиОбъект.Записать(РежимЗаписиДокумента.Проведение);
//shell
ВременныйФайлСкриптаPowerShell = ПолучитьИмяВременногоФайла("ps1");
ТекстСкриптаPowerShell = "$accountName = '"+ИмяПольз+"'
|$accountNameMail = '"+ИмяПольз+"@company.ru'
|$subject='Добро пожаловать!'
|$body = ""
|<html>
|<head>
|<meta http-equiv=Content-Type content='text/html; charset=windows-1251'>
|<meta name=Generator content='Microsoft Word 15 (filtered)'>
| <title>Добро пожаловать!</title>
| <style>
| body {
| font-family: Arial, sans-serif;
| margin: 20px;
| background-color: #f5f5f5;
| padding-right: 300px;
| padding-left: 300px;
| }
| h1 {
| color: #333;
| font-size: 24px;
| padding-bottom: 10px;
| text-align: center;
| }
| p {
| color: #666;
| font-size: 16px;
| line-height: 1.5;
| text-align: center;
| }
| ul {
| list-style-type: none;
| padding: 0;
| text-align: center;
| }
| li {
| padding-bottom: 10px;
| text-align: left;
| }
| a {
| color: #0066cc;
| text-decoration: none;
| font-size: 18px; /* Увеличиваем размер текста ссылок */
| }
| a:hover {
| text-decoration: underline;
| }
| li {
| padding-bottom: 10px;
| text-align: left;
| border: 2px solid black; /* Добавляем обводку */
| border-radius: 10px; /* Добавляем закругление */
| padding: 10px; /* Увеличиваем внутренний отступ */
|}
| </style>
|</head>
|<body>
| <h1>Добро пожаловать!</h1>
| <p>Уважаемый сотрудник!</p>
| <p>Мы рады видеть вас частью нашей команды. Когда вы отправитесь в путь вместе с нами, мы хотим обеспечить плавный переход и предоставить вам полезные ресурсы.</p>
|</body>
|</html>
|""
|Send-MailMessage -From 'it@company.ru' -To $accountNameMail -Subject $subject -Body $body -BodyAsHtml ` -Encoding 'UTF8' -SmtpServer '167.16.2.11'";
ЗаписьТекстаСкриптаPowerShell = Новый ТекстовыйДокумент;
ЗаписьТекстаСкриптаPowerShell.УстановитьТекст(ТекстСкриптаPowerShell);
ЗаписьТекстаСкриптаPowerShell.Записать(ВременныйФайлСкриптаPowerShell, КодировкаТекста.Системная);
ЗапуститьПриложение("powershell "+ВременныйФайлСкриптаPowerShell,,Ложь);
Исключение
ТекстОшибки = "Ошибка в процедуре ВыгрузитьСобытиеВOutlookНаСервере для события "+ДокументДляВыгрузки+". Описание ошибки: " + ОписаниеОшибки();
ЗаписьЖурналаРегистрации("ВыгрузкаВAD/Outlook",УровеньЖурналаРегистрации.Ошибка,,ТекстОшибки);
ДокументДляВыгрузкиОбъект = ДокументДляВыгрузки.ПолучитьОбъект();
ДокументДляВыгрузкиОбъект.ДатаВыгрузкиВOutlook = Неопределено;
ДокументДляВыгрузкиОбъект.СтатусВыгрузкиВOutlook = ОписаниеОшибки();
ДокументДляВыгрузкиОбъект.Записать(РежимЗаписиДокумента.Проведение);
ВызватьИсключение(ТекстОшибки);
КонецПопытки;
КонецПроцедуры