[Из песочницы] Автоматизация кадровых изменений на PowerShell
Эта статья посвящена автоматизации операций по созданию, перемещению и увольнению людей в соответствии с кадровыми изменениями, сделанными в 1С.
Принцип работы скрипта заключается в парсинге выгружаемых из 1С данных пользователя и присвоении этих данных переменным скрипта с дальнейшим их использованием.
В нашей компании после заведения пользователя в 1C создается CSV файл с данными, пример ниже:
document type | userName | FIO | Department | Department |
---|---|---|---|---|
прием на работу | USERtester1 | Иванов Иван Иванович | Диспонент | Отдел диспозиции и оформления документов |
перемещение | USERtester2 | Петров Иван Иванович | Менеджер по пролонгации | Отдел кредитования и страхования |
увольнение | USERtester3 | Сидоров Иван Иванович | Менеджер по пролонгации | Отдел кредитования и страхования |
Скрипт содержит три функции (usrcreate; usrmove; usrdelete) в соответствии с типами операций:
Прием на работу
Ищем шаблон пользователя на основе должности и названия отдела, после нахождения получаем необходимые атрибуты и группы, записываем их в нового пользователя, вместе с тем создается и подключается домашняя папка, а также привязывается почтовый адрес. На почту отправляется отчет с именем пользователя, ФИО и списком групп, в которые он был добавлен.
Кадровое перемещение
Находим шаблон пользователя по новой должности и новому отделу сотрудника, с которого мы получаем новый список групп и адрес OU, после нахождения удаляем старые группы у перемещаемого пользователя и добавляем его в новые, одновременно переносим его в OU, соответствующий новому отделу (если есть такое деление в AD), и меняем должности на новые соответственно. На почту отправляется отчет с новыми должностью, отделом и группами.
Увольнение
Отключаем почтовый ящик, удаляем пользователя из всех групп, перемещаем его в папку для отключенных пользователей и отключаем его аккаунт. На почту отправляется отчет о том, что пользователь отключен и уволен.
Скрипт включает в себя ряд проверок:
Проверка на необходимость запуска оснасток Exchange и Active Directory
В данной проверке производится поиск данных для обработки если они не найдены оснастки загружаться не будут, что сэкономит примерно 7 секунд времени.
Проверка на существование данных для обработки в переменных $getstaff|$movestaff|$delstaff
Для запуска функций создания, перемещения и удаления пользователей.
Проверка на существование создаваемого пользователя
Для проверки дубликатов заданий на создание пользователя.
Проверка на существование сетевой папки пользователя
Для обхода ошибки о существовании папки.
Проверка должности и департамента
Для проверки на дублирование заявки на перемещение, когда пользователь уже был перемещен на новую должность.
Проверка на увольнение пользователя
Для проверки на дублирование заявки на увольнение, когда пользователь уже был уволен.
$smtpserv | Почтовая отправка (Сервер) |
---|---|
$smtpfrom | Почтовая отправка (От кого) |
$smtpto | Почтовая отправка (Кому) |
$opertype | Тип операции над пользователем |
$usrname | SamAccountName |
$FIO | Фамилия Имя Отчество |
$curdate | Текущая дата в формате день.месяц.год |
$del | Элемент массива $delstaff |
$delstaff | Данные пользователя для увольнения |
$department | Отдел |
$dir | Место куда 1С выгружает CSV |
$get | Элемент массива $getstaff |
$getstaff | Данные пользователя для приема на работу |
$groups | Список скопированных групп для отчета |
$move | Элемент массива $movestaff |
$movestaff | Данные пользователя для кадрового перемещения |
$newusername | Имя |
$newusersurname | Фамилия |
$Position | Должность |
$sdel | Разспличенный $del |
$sget | Разспличенный $get |
$smove | Разспличенный $move |
$shablon | SamAccountName шаблона пользователя |
$spisokf | Список файлов в директории выгрузки из 1С |
$todayf | Файл в котором находятся кадровые изменения за сегодняшний день |
$usrcopyfrom | Шаблон пользователя |
$usrexist | Логин пользователя для проверки на существование |
$usrpath | Расположение пользователя в AD |
$usrprop | Свойства пользователя шаблона |
$usrdomain | Ваш домен |
$Session | Сессия с консолью управления Exchange |
$usrshare | Адрес папки пользователя на сетевом хранилище |
$pass | Временный пароль пользователя |
$company | Название компании |
$usrstate | Область расположения компании |
$usrCity | Город |
$usrStreetAddress | Улица дом корпус |
$curuserpath | Текущее расположение перемещаемого пользователя в AD |
$newuserpath | Целевое расположение перемещаемого пользователя в AD |
$usrmoveddep | Текущий департамент пользователя для проверки на дублирование приказа на перемещение |
$usrmovedtit | Текущая должность пользователя для проверки на дублирование приказа на перемещение |
Элементы в массивах $get|$move|$del
[0] | Тип операции прием на работу/перемещение/увольнение |
---|---|
[1] | SamAccountName |
[2] | ФИО |
[3] | Должность |
[4] | Отдел |
Сам скрипт:
#Переменные почтовой отправки
$smtpserv = "post.domain.local"
$smtpfrom = "AUTOUSERCHANGER@domain.local"
$smtpto = "sysadmin@domain.local"
$encoding = [System.Text.Encoding]::UTF8
$smtpBody = ""
#Директория в которую выгружаются файлы из 1С
$dir= "\\fileserver\1C\"
#Домен
$usrdomain="domain.local"
#Получение файлов csv для обработки
$spisokf=Get-Childitem -File -Path $dir*.csv | Select-Object -ExpandProperty Name
#Поиск запланированных на сегодня кадровых изменений
$curdate=Get-Date -Format dd.MM.yyyy
$todayf=$spisokf | Select-String $curdate
#Парсинг файлов и загон данных в переменные
$getstaff= Get-Content $dir$todayf |Select-String "прием на работу"
$movestaff= Get-Content $dir$todayf |Select-String "перемещение"
$delstaff= Get-Content $dir$todayf |Select-String "увольнение"
#Включение поддержки EXCHANGE и ActiveDirectory
if ($getstaff -ne $null -or $movestaff -ne $null -or $delstaff -ne $null)
{
$Session=New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://post.domain.local/PowerShell/ -Authentication Kerberos
Import-PSSession $Session -AllowClobber | out-null
Import-Module ActiveDirectory
}
else
{
Write-Host "Нет данных для операций над пользователями"
}
#Создание пользователя
function usrcreate ()
{
#Перебор массива принимаемых на работу
ForEach ($get in $getstaff)
{
#Сплит массива
$sget=$get -split (";")
$opertype = $sget[0]
$usrname=$sget[1]
$FIO=$sget[2]
$Position=$sget[3]
$department=$sget[4]
#Проверка на существование пользователя
$usrexist=Get-ADUser -filter {(SamAccountName -eq $usrname)} | Select-Object -ExpandProperty SamAccountName
if ($usrexist -eq $null)
{
#Шара пользовательских папок
$usrshare="\\FILESERVER\Users\$usrname"
#Поиск пользователя для шаблона
$shablon=Get-ADUser -filter { (physicalDeliveryOfficeName -like $department) -and (title -like $Position) -and (Enabled -eq $true) -and (SamAccountName -ne $usrname)} | Select-Object -ExpandProperty SamAccountName
$usrcopyfrom=$shablon[1]
#-Path
$usrprop= Get-ADUser -Identity $usrcopyfrom | Select-Object -ExpandProperty DistinguishedName
$usrpath= ($usrprop -split ',',2)[1]
#-name
$newusername=($FIO-split ' ')[1]
#-Surname
$newusersurname=($FIO-split ' ')[0]
#-AccountPassword
$pass="Qwerty01"
#-company
$company= Get-ADUser -Identity $usrcopyfrom -Properties Company | Select-Object -ExpandProperty company
#-State
$usrstate= Get-ADUser -Identity $usrcopyfrom -Properties State | Select-Object -ExpandProperty State
#-City
$usrCity= Get-ADUser -Identity $usrcopyfrom -Properties City | Select-Object -ExpandProperty City
#-StreetAddress
$usrStreetAddress= Get-ADUser -Identity $usrcopyfrom -Properties StreetAddress | Select-Object -ExpandProperty StreetAddress
#Создание пользователя
New-ADUser `
-name $FIO `
-AccountPassword (ConvertTo-SecureString $pass -AsPlainText -Force) `
-ChangePasswordAtLogon $true `
-Company $company `
-Department $department `
-Description $Position `
-DisplayName $FIO `
-Enabled $true `
-HomeDirectory $usrshare `
-HomeDrive "БУКВА ДИСКА ДОМАШНЕЙ ПАПКИ" `
-Path $usrpath `
-PostalCode "ПОЧТОВЫЙ ИНДЕКС ЦИФРАМИ" `
-SamAccountName $usrname `
-UserPrincipalName "$usrname@$usrdomain" `
-State $usrstate `
-StreetAddress $usrStreetAddress `
-Surname $newusersurname `
-Title $Position `
-GivenName $newusername `
-City $usrCity `
-Office $department ` | out-null
#Ожидание создания пользователя
Start-Sleep -Seconds 10
#Копирование групп с пользовательского шаблона
$groups=Get-ADUser -Identity $usrcopyfrom -Properties memberof | Select-Object -ExpandProperty memberof|Add-ADGroupMember -Members $usrname -PassThru | Select-Object -ExpandProperty SamAccountName
#Создание пользовательской папки на сетевом диске (с проверкой есть ли папка с таким именем)
if(!(Test-Path -Path $usrshare ))
{
New-item $usrshare -type directory | out-null
$acl = Get-Acl $usrshare
$acl | Format-List
$acl.GetAccessRules($true, $true, [System.Security.Principal.NTAccount])
$acl.SetAccessRuleProtection($true, $true)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule ("$usrdomain\$usrname","FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.addAccessRule($rule)
Set-Acl $usrshare $acl | out-null
}
else
{
$acl = Get-Acl $usrshare
$acl | Format-List
$acl.GetAccessRules($true, $true, [System.Security.Principal.NTAccount])
$acl.SetAccessRuleProtection($true, $true)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule ("$usrdomain\$usrname","FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.addAccessRule($rule)
Set-Acl $usrshare $acl | out-null
}
#Включение ящика пользователя
Enable-Mailbox "$usrname@$usrdomain" -Database "ИМЯ БАЗЫ ДАННЫЙ ПОЧТЫ" | out-null
#Вывод групп для отчета
foreach ($group in $groups) {$smtpBody = $smtpBody +$group+"`n`n"}
#Отправка отчета на почту
Send-MailMessage -From $smtpfrom -Subject $opertype -To $smtpto -Body "Пользователь $FIO ($usrname) ""$Position"" отдела ""$department"" создан.`n`nДобавлен в группы:`n$smtpBody" -SmtpServer $smtpserv -Encoding $encoding
#Очистка переменных
$smtpBody=""
}
else
{
#Отправка отчета на почту
Send-MailMessage -From $smtpfrom -Subject $opertype -To $smtpto -Body "Пользователь $FIO ($usrname) уже существует." -SmtpServer $smtpserv -Encoding $encoding
}
#Удаление обработанной строки из файла
(Get-Content $dir$todayf) | Where-Object {$_ -notmatch $get} | Set-Content -Path $dir$todayf -Force
}
}
#Запуск создания пользователя
if ($getstaff -ne $null)
{
#Запуск функции создания пользователя
#usrcreate
#Ожидание завершения процессов
Start-Sleep -Seconds 10
}
else
{
Write-Host "Нет пользователей для создания"
}
#Кадровое перемещение
function usrmove ()
{
ForEach ($move in $movestaff)
{
#Сплит массива
$smove=$move -split (";")
$opertype = $smove[0]
$usrname=$smove[1]
$FIO=$smove[2]
$Position=$smove[3]
$department=$smove[4]
#Проверка на существование пользователя
$usrmoveddep =Get-ADUser -Identity $usrname -Properties Department |Select-Object -ExpandProperty Department
$usrmovedtit =Get-ADUser -Identity $usrname -Properties title |Select-Object -ExpandProperty title
if ($usrmoveddep -ne $department -or $usrmovedtit -ne $Position)
{
#Поиск пользователя для шаблона
$shablon=Get-ADUser -filter { (physicalDeliveryOfficeName -like $department) -and (title -like $Position) -and (Enabled -eq $true) } | Select-Object -ExpandProperty SamAccountName
$usrcopyfrom=$shablon[1]
#Замена должности и отдела пользователя
Set-ADUser -Identity $usrname -Department $department -Description $Position -Title $Position -Replace @{physicalDeliveryOfficeName = $department}
#Текущее расположение перемещаемого пользователя
$curuserpath= Get-ADUser -Identity $usrname |Select-Object -ExpandProperty DistinguishedName
#Целевое расположение перемещаемого пользователя
$usrprop= Get-ADUser -Identity $usrcopyfrom | Select-Object -ExpandProperty DistinguishedName
$newusrpath= ($usrprop -split ',',2)[1]
#Перемещение пользователя
Move-ADObject -Identity $curuserpath -TargetPath $newusrpath
#Отключаем запрос на подтверждение при удалении из групп, и вывод ошибок.
$ConfirmPreference = "None"
$ErrorActionPreference = "SilentlyContinue"
#Удаление всех групп у перемещаемого пользователя, кроме domain users
Remove-ADPrincipalGroupMembership -Identity $usrname -MemberOf $(Get-ADPrincipalGroupMembership -Identity $usrname | Where-Object {$_.DistinguishedName -ne 'CN=Domain Users,CN=Users,DC=domain,DC=local'})
#Копирование групп с пользовательского шаблона
$groups=Get-ADUser -Identity $usrcopyfrom -Properties memberof | Select-Object -ExpandProperty memberof|Add-ADGroupMember -Members $usrname -PassThru | Select-Object -ExpandProperty SamAccountName
#Вывод групп для отчета
foreach ($group in $groups) {$smtpBody = $smtpBody +$group+"`n`n"}
#Отправка отчета на почту
Send-MailMessage -From $smtpfrom -Subject $opertype -To $smtpto -Body "Пользователь $FIO ($usrname) ""$Position"" отдела ""$department"" перемещен.`n`nДобавлен в группы:`n$smtpBody" -SmtpServer $smtpserv -Encoding $encoding
#Очистка переменных
$smtpBody=""
}
else
{
#Отправка отчета на почту
Send-MailMessage -From $smtpfrom -Subject $opertype -To $smtpto -Body "Пользователь $FIO ($usrname) уже имеет должность ""$Position"" отдела ""$department""" -SmtpServer $smtpserv -Encoding $encoding
}
#Удаление обработанной строки из файла
(Get-Content $dir$todayf) | Where-Object {$_ -notmatch $move} | Set-Content -Path $dir$todayf -Force
}
}
#Запуск перемещения пользователя
if ($movestaff -ne $null)
{
#Запуск функции создания пользователя
#usrmove
#Ожидание завершения процессов
Start-Sleep -Seconds 10
}
else
{
Write-Host "Нет пользователей для перемещения"
}
#Увольнение
function usrdelete ()
{
ForEach ($del in $delstaff)
{
#Сплит массива
$sdel=$del -split (";")
$opertype = $sdel[0]
$usrname=$sdel[1]
$FIO=$sdel[2]
$Position=$sdel[3]
$department=$sdel[4]
#Проверка на существование пользователя
$usrdeleted =Get-ADUser -Identity $usrname | Where-Object {$_.Enabled -eq $false}
if ($usrdeleted -eq $null)
{
#Отключаем запрос на подтверждение при удалении из групп, и вывод ошибок.
$ConfirmPreference = "None"
$ErrorActionPreference = "SilentlyContinue"
#Отключение ящика пользователя
Disable-Mailbox -Identity "$usrname@$usrdomain" -confirm:$false
#Удаление всех групп у перемещаемого пользователя, кроме domain users
Remove-ADPrincipalGroupMembership -Identity $usrname -MemberOf $(Get-ADPrincipalGroupMembership -Identity $usrname | Where-Object {$_.DistinguishedName -ne 'CN=Domain Users,CN=Users,DC=domain,DC=local'})
#Текущее расположение перемещаемого пользователя
$curuserpath = Get-ADUser -Identity $usrname |Select-Object -ExpandProperty DistinguishedName
#Перемещение пользователя в контейнер отключенных пользователей
Move-ADObject -Identity $curuserpath -TargetPath "OU=USER_DISABLE,OU=TO_DELETE_USER_COMPUTER_GROUP_OU,DC=domain,DC=local"
#Отключение аккаунта пользователя
Disable-ADAccount $usrname
#Отправка отчета на почту
Send-MailMessage -From $smtpfrom -Subject $opertype -To $smtpto -Body "Пользователь $FIO ($usrname) ""$Position"" отдела ""$department"" уволен и отключен." -SmtpServer $smtpserv -Encoding $encoding
}
else
{
#Отправка отчета на почту
Send-MailMessage -From $smtpfrom -Subject $opertype -To $smtpto -Body "Пользователь $FIO ($usrname) ""$Position"" отдела ""$department"" уже был отключен." -SmtpServer $smtpserv -Encoding $encoding
}
#Удаление обработанной строки из файла
(Get-Content $dir$todayf) | Where-Object {$_ -notmatch $del} | Set-Content -Path $dir$todayf -Force
}
}
#Запуск перемещения пользователя
if ($delstaff -ne $null)
{
#Запуск функции создания пользователя
usrdelete
#Ожидание завершения процессов
Start-Sleep -Seconds 10
}
else
{
Write-Host "Нет пользователей для перемещения"
}