Search
Write a publication
Pull to refresh

Автоматизация создания пользователей или как я исключил себя из кадровой цепочки

Итак, я сотрудник бюджетной организации с достаточно объёмной для такого типа учреждения IT инфраструктурой и достаточно большим штатом сотрудников. Каждый приход сотрудника сопровождается заведением нового пользователя в AD и выдачу ему логина и пароля, что для меня просто рутина и отвлекает от мыслей о вселенной. Так же присутствует человеческий фактор, меня может не быть на месте, я могу опечататься при создании. Да и ко всему у нас имелась достаточно не безопасная схема - всем выдавался одинаковый временный пароль. Всё это сподвигло меня на написание скрипта, который будет получать данные из 1С ЗУП, создавать на основе этих данных пользователя в AD и высылать эти данные на WathsApp уже сотруднику, причём пароль случайно сгенерированный. Вообще есть готовые обработки для 1С, позволяющие исполнить этот функционал, но они либо платные, либо не работающие с моей конфигурацией, а программист 1С из меня не очень. Однако выгрузка в 1С есть безо всякого изменения кода. Итак, поехали по пунктам.

1. Создадим отчёт и автоматическую выгрузку его. В моей версии конфигурации это выглядит так: кадровые отчёты - персональные данные сотрудников, выбираем настройку отчёта и указываем поле ФИО, номер телефона и дату приёма на работу (указываем текущую дату, чтобы не экспортировать тех кого уже приняли на работу, в режиме настройки отчёта нельзя выбрать чтобы каждый день была сегодняшняя дата, это можно настроить только в конфигураторе, но пока остановимся на просто крайней дате, дальше объясню почему). Далее настроим выгрузку отчёта, это настраивается там же где отправка на почту, значок в виде конверта. Я выбрал выгрузку в сетевую папку, обратите внимание, что для папки должны быть права на запись тех пользователей, которые работают в базе ибо файловый вариант базы автоматически отправляет отчёты, только если запущен клиент. Отчёт лучше формировать в txt. Убедившись, что отчёт сформирован и выгружен, можно переходить ко второму пункту - это скрипт на Power shell.

2. Скрипт сначала преобразует выгруженный файл в читаемый для PS, убирает лишние символы и пересохраняет, затем считывает снова уже в правильном формате, преобразует ФИО с помощью функции транслитерации, создаёт пользователя согласно необходимым критериям (в данном случае для создания логина используется первая буква имени, точка, фамилия), пароль генерируется с помощью функции генерации случайных символов, функция настраиваемая, по количеству символов и содержанию букв, цифр и спец символов (у меня спец символы не используются, многие пользователи не знают, где они на клавиатуре). В цикле создания пользователя используется проверка на выполнение команды, если пользователя нет и команда создания выполнена запускается скрипт на питоне, отправляющий сообщение, если пользователь есть и команда не выполнена, соответственно скрипт прерывается. Это позволяет не редактировать дату приёма в выгрузке 1с, имеющийся пользователь просто не создастся. Прерывание скрипта вызвано тем, что скрипт питона после работы не завершает процесс питона и следующее выполнение скрипта не срабатывает. Здесь жду каких-то подсказок ибо у меня нет мыслей на этот счёт, я пробовал и через команду kill, и пр., не срабатывает.

Сам скрипт собственно, с комментами:

Import-Module activedirectory 	#строка говорит сама за себя
function global:Translit {		 #начало функции транслитерации
param([string]$inString)
$Translit = @{
[char]'а' = "a"
[char]'А' = "A"
[char]'б' = "b"
[char]'Б' = "B"
[char]'в' = "v"
[char]'В' = "V"
[char]'г' = "g"
[char]'Г' = "G"
[char]'д' = "d"
[char]'Д' = "D"
[char]'е' = "e"
[char]'Е' = "E"
[char]'ё' = "yo"
[char]'Ё' = "Yo"
[char]'ж' = "zh"
[char]'Ж' = "Zh"
[char]'з' = "z"
[char]'З' = "Z"
[char]'и' = "i"
[char]'И' = "I"
[char]'й' = "j"
[char]'Й' = "J"
[char]'к' = "k"
[char]'К' = "K"
[char]'л' = "l"
[char]'Л' = "L"
[char]'м' = "m"
[char]'М' = "M"
[char]'н' = "n"
[char]'Н' = "N"
[char]'о' = "o"
[char]'О' = "O"
[char]'п' = "p"
[char]'П' = "P"
[char]'р' = "r"
[char]'Р' = "R"
[char]'с' = "s"
[char]'С' = "S"
[char]'т' = "t"
[char]'Т' = "T"
[char]'у' = "u"
[char]'У' = "U"
[char]'ф' = "f"
[char]'Ф' = "F"
[char]'х' = "h"
[char]'Х' = "H"
[char]'ц' = "c"
[char]'Ц' = "C"
[char]'ч' = "ch"
[char]'Ч' = "Ch"
[char]'ш' = "sh"
[char]'Ш' = "Sh"
[char]'щ' = "sch"
[char]'Щ' = "Sch"
[char]'ъ' = ""
[char]'Ъ' = ""
[char]'ы' = "i"
[char]'Ы' = "I"
[char]'ь' = ""
[char]'Ь' = ""
[char]'э' = "e"
[char]'Э' = "E"
[char]'ю' = "u"
[char]'Ю' = "U"
[char]'я' = "ia"
[char]'Я' = "Ia"
}
$outCHR=""
foreach ($CHR in $inCHR = $inString.ToCharArray())
{
if ($Translit[$CHR] -cne $Null )
{$outCHR += $Translit[$CHR]}
else
{$outCHR += $CHR}
}
Write-Output $outCHR
} 							#конец функции транслитерации
Function GenPassword ($PasswordLength) 	#начало функции генерации пароля
{
    $rand = New-Object System.Random
    $PassNotCheck = $true
    while ($PassNotCheck)
    {
       $Password = $null
        1..$PasswordLength | % { 
            switch (Get-Random -Minimum 1 -Maximum 4)
            {
                1 {$Password = $Password + [char]$rand.next(65,91)}  #A-Z
               2 {$Password = $Password + [char]$rand.next(48,58)}  #0-9
                3 {$Password = $Password + [char]$rand.next(97,123)} #a-z
            }
        }   
    if (($Password -match "[0-9]") -and ($Password -cmatch "[a-z]") -and ($Password -cmatch "[A-Z]")) {$PassNotCheck = $false}
    }
    Write-Output $Password
} 								#конец фунции генерации пароля
Remove-Item \\fs01\wallp$\Выгрузка\1.csv 		#удаляем предыдущий файл
Rename-Item "\\fs01\wallp$\Выгрузка\*.txt" "1.csv"  #переименовываем файл выгрузки
(Get-Content \\fs01\wallp$\Выгрузка\1.csv) | foreach-object{ $_ -replace "Сотрудник", "Surname Name Fathername"} | set-content \\fs01\wallp$\Выгрузка\1.csv 	#заменяем слова, сформированные отчётом 1с нужными нам
(Get-Content \\fs01\wallp$\Выгрузка\1.csv) | foreach-object{ $_ -replace "Телефон мобильный", "Tel"} | set-content \\fs01\wallp$\Выгрузка\1.csv 			#Заменяем столбец телефон
(Get-Content \\fs01\wallp$\Выгрузка\1.csv) | foreach-object{ $_ -replace "\(", ""} | set-content \\fs01\wallp$\Выгрузка\1.csv 						#убираем лишние скобки, которые могли быть в отчёте, обратите внимание как они обособлены
(Get-Content \\fs01\wallp$\Выгрузка\1.csv) | foreach-object{ $_ -replace "\)\ ", ""} | set-content \\fs01\wallp$\Выгрузка\1.csv
(Get-Content \\fs01\wallp$\Выгрузка\1.csv) | foreach-object{ $_ -replace "-", ""} | set-content \\fs01\wallp$\Выгрузка\1.csv 							#убираем тире
(Get-Content \\fs01\wallp$\Выгрузка\1.csv) | foreach-object{ $_ -replace "`t8", " +7"} | set-content \\fs01\wallp$\Выгрузка\1.csv 						#убираем восьмёрку с табуляцией и заменяем её на читаемую для скрипта +7, обратите внимание на символ табуляции
(Get-Content \\fs01\wallp$\Выгрузка\1.csv) | foreach-object{ $_ -replace "\+7 ", "+7"} | set-content \\fs01\wallp$\Выгрузка\1.csv 						# пробелы лишние тоже
(Get-Content \\fs01\wallp$\Выгрузка\1.csv) | foreach-object{ $_ -replace "`t", " "} | set-content \\fs01\wallp$\Выгрузка\1.csv 						#лишняя табуляция
(Get-Content \\fs01\wallp$\Выгрузка\1.csv) | foreach-object{ $_ -replace " ", ","} | set-content \\fs01\wallp$\Выгрузка\1.csv -encoding utf8 				#в самый последний момент заменяем пробелы запятыми, чтобы они стали разделителями и указываем кодировку 
$H = Get-Date -Format "HH" 				#переменная часа для передачи в питон
$M = Get-Date -Format "mm" 				#переменная минут для питона
Import-Csv "\\fs01\wallp$\Выгрузка\1.csv" | ForEach-Object {		 #начало прочтения уже отредактированного файла и перебор
$ou = 'OU=Test,OU=Сотрудники,DC=panspb,DC=local' 				#папка в AD куда будут создаваться пользователи
$Temppass = GenPassword -PasswordLength 7 					#генерируем в переменную пароль длинной в 7 символов
$sa = translit($_.name[0]) 								#переводим первую букву имени, первая это нулевая, т.к. строка это массив из символов, из кириллицы в латиницу и записываем в переменную
$sa = $sa+"." 										#прибавляем точку к имени
$su = translit($_.surname) 								#переводим фамилию
$sa = $sa + $su 										#склеиваем имя и фамилию и получаем будущий логин
$NA = $_.surname + " " + $_.name + " " + $_.fathername 			#склеиваем фио и получаем отображаемое имя
New-ADUser -Name $NA ` 									#создаём пользователя с переменной, в которой указан фио
-GivenName $_.name ` 									#добавляем имя
-Surname $_.surname ` 									#фамилию
-SamAccountName $sa ` 									#логин
-AccountPassword (ConvertTo-SecureString $temppass -AsPlainText -force) -Enabled $true ` #пароль
-Path $ou ` 										#директория в AD 
-DisplayName $na ` 									#отображаемое имя
-UserPrincipalName ($sa + "@panspb.local") ` 					#полное доменное имя
-CannotChangePassword 0 ` 								#разрешено менять пароль
-ChangePasswordAtLogon 1 								#требование смены пароля
if($?){ 											#проверка выполнения команды
C:\Python37\python.exe \\fs01\wallp$\Выгрузка\telsh.py --tel=$_.tel --t=$sa,$Temppass --h=$H --m=$M 			#запуск скрипта питона, в который передаётся номер телефона, логин и пароль в качестве текста и время отправки сообщения 
Add-ADGroupMember -Identity "Сотрудники" -Members $sa 			#добавление в группу безопасности, если требуется
exit		 #прерывание скрипта
}
}

Далее переходим к самому скрипту питона для отправки сообщения.

3. Скрипт отправки сообщения в WhatsApp.

Перед тем как работать со скриптом нужно установить сам питон естественно и установить т.н. пип, на этом я не буду заострять внимение, т.к. для каждой системы и каждого питона своя инструкция. После установки пипа нужно установить библиотеку piwhatkit. После этих действий можно переходить к ватсапу, на Пк с которого выполняется скрипт должен быть запущен WhatsApp Web и должна быть синхронизация с аккаунтом от имени которого будут отправляться сообщения, это может быть как корп акк, так и личный.

import argparse 											#это библиотека для передачи параметров из вне
parser = argparse.ArgumentParser(description='A tutorial of argparse!')
parser.add_argument("--tel") 									#аргумент телефона
parser.add_argument("--t") 									#аргумент текста
parser.add_argument("--h") 									#аргумент часа
parser.add_argument("--m") 									#аргумент минут
args = parser.parse_args() 									#массив аргументов
tel = args.tel 											#записываем полученный аргумент телефона в переменную
t = args.t 												#записываем аргумент текста
h = int(args.h) 											#записываем аргумент часа и переводим его в числовой формат, т.к. приходит он как строка
m = int(args.m) 											#то же самое для минут
m = m + 2 												#необходимо увеличить минуту на 2, чтобы дать время на запуск браузера и отправку сообщения
import pywhatkit as kit 									#импортруем библиотеку для отправки
kit.sendwhatmsg(tel, t, h, m) 								#отправляем сообщение с переданными параметрам
exit()

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

Собственно задача выполнена, сотрудник отдела кадров добавляет нового сотрудника в ЗУП, срипт отсылает учётные данные человеку на WhatsApp, системный администратор в этом процессе не участвует. Я добавил этот скрипт в планировщик с периодичностью в 30 минут, второй строкой я добавил закрытие браузера, т.к. каждое новое сообщение отправляется из новой вкладки. Можно в скрипт добавить строку создания почты в Эксчейндже, но у меня для этого отдельный скрипт. На будущее я запланировал синхронизацию с ПО LMS школа, это спец ПО для образовательных учреждений, если у кого-нибудь есть по этому готовые наработки, просьба поделиться.

Жду комментариев и предложений по оптимизации, надеюсь кому-то пригодятся моти строки.

Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.