Когда новый сотрудник выходит на работу, обычно мало просто создать ему аккаунт в Active Directory: нужно включить его в группы безопасности, создать личную папку на сетевом диске, почтовый ящик, добавить аккаунт в ERP\CRM систему… Все это частично решается копированием аккаунта, но тогда нужно еще вовремя вспомнить и правильно настроить атрибуты Active Directory.


Но есть и более изящные варианты решения задачи. Так что, если вам надоело создавать аккаунты вручную ? приглашаю под кат.


Шаблоны и PowerShell


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


Я буду разбирать более интересные примеры, по сути основанные на этом методе.


Такой скрипт может являться «бэкендом», которому передается предварительно подготовленный «фронтендом» файл в любом текстовом формате: JSON, XML или вовсе CSV.


Например, можно подготовить JSON файл для создания пользователя и папки для него такого вида:


{
    "ActiveDirectory": {
        "UserAccounts": [
            {
                "FirstName" : "Иван",
                "LastName" : "Иванов",
                "Department": "Бухгалтерия",
                "UserName": "Iivanov"
            }
        ]
    },

    "UserHomeFolders" : [
        {
            "Name": "ИвановИ"
        }
    ]
}

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


[CmdletBinding()]
param(
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$TemplateFilePath = 'C:\temp\users.json'
)

$users = Get-Content -Path $TemplateFilePath -Raw | ConvertFrom-Json
$users.ActiveDirectory.UserAccounts | ForEach-Object {
    if ($adUser = Get-AdUser -Filter "samAccountName -eq '$($_.UserName)'") {
        $setParams = @{
            Identity = $_.UserName
        }

        if ($adUser.GivenName -ne $_.FirstName) {
            $setParams.GivenName = $_.FirstName
        }

        if ($adUser.SurName -ne $_.LastName) {
            $setParams.SurName = $_.LastName
        }

        if (@($setParams.Keys).Count -gt 1) {
            $setParams
            Write-Verbose -Message "Обновляем существующего пользователя [$($_.UserName)] "
            Set-AdUser @setParams
        } else {
            Write-Verbose -Message "Пользователь [$($_.UserName)] уже создан"
        }

    } else {
        Write-Verbose -Message "Создание нового пользователя [$($_.UserName)]..."
        New-AdUser -Name $_.UserName -GivenName $_.FirstName -SurName $_.LastName -Path "ou=$($_.Department),dc=domain,dc=com"
    }
}

$fileServerShare = 'C:\HomeFolders'
$users.UserHomeFolders | ForEach-Object {
    $folderPath = Join-Path -Path $fileServerShare -ChildPath $_.Name

    if (-not (Test-Path -Path $folderPath -PathType Container)) {
        Write-Verbose -Message "Создаем папку [$($folderPath)]..."
        $null = New-Item -Path $folderPath -Type Directory
    } else {
        Write-Verbose -Message "Папка [$($folderPath)] уже создана"
    }
}

Теперь можно запустить получившийся скрипт и насладиться его работой:



Работа командлета.


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

Если командлет можно настроить на запуск по расписанию раз в 5 минут, то осталось придумать, что будет формировать JSON. Это может быть и простой веб-интерфейс, GUI на том же PowerShell и прочие 1С. Интересный пример использования в качестве фронта Google Forms и заодно создание пользователям ящика в G Suite рассмотрен в материале «Ещё один пример автоматизации или PowerShell + Google Apps Script».


Разберу еще несколько примеров автоматизации, облегчающих жизнь.


Задаем права на папки


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


Чтобы уменьшить негатив, еще до появления PowerShell был разработан скрипт на vbs. Раз в сутки он подключался к AD и собирал оттуда свежесозданных пользователей. А потом создавал папку по стандарту и задавал нужные права при помощи xcacls.vbs такой командой:


WshShell.Run "cscript.exe C:\xcacls.vbs " + """" + folder + """" +" "+ "/I COPY /R users /G domain\"+ user+ ":F"

Где user ? это имя нового пользователя, folder ? путь к свежесозданной папке, а domain ? наш домен.


Позже для создания пользователей был уже разработан сложный механизм на AutoIT с GUI. Он формировал имя учетной записи по правилам транслитерации, создавал пользователей в 1С и даже выдавал проксимити-карты для доступа на территорию офиса. Права на папки в этом механизме задаются при помощи библиотеки Permissions.au3, которая использует системные dll advapi32.dll и kernel32.dll.


Часть скрипта для нужных разрешений:


FileWriteLine($logfile, "создаем папку "&$path)
 local $aPermissions[2][3]
$aPermissions[0][0]="domain\"& $username
$aPermissions[0][1]=1
$aPermissions[0][2]=$GENERIC_ALL
$aPermissions[1][0]="Users"
$aPermissions[1][1]=1
$aPermissions[1][2]=""
_EditObjectPermissions($path, $aPermissions,$SE_FILE_OBJECT,"",1)
 FileWriteLine($logfile, "задаем права")
 _ClosePermissionResources()

В PowerShell аналогичная выдача прав будет выглядеть примерно так:


$acl = Get-Acl $path
$acl.SetAccessRuleProtection($true,$true)
$acl.Access |where {$_.IdentityReference -eq "Domain\Users"} | %{$acl.RemoveAccessRule($_)}
$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule ($username,"FullControl","ContainerInherit,ObjectInherit","None","Allow")
$acl | Set-Acl $path

Пожалуй, управление ACL ? это то немногое, что на PowerShell реализуется нетривиально. Перейдем к тому, в чем PowerShell силен и прост.


Добавляем почту и телефон


Если у вас установлен Exchange как почтовый сервер, то создавать пользователей сразу с почтовым ящиком поможет командлет New-Mailbox. Для создания пользователя в первоначальном скрипте можно использовать такую команду:


New-Mailbox -UserPrincipalName $_.UserName@example.com -Alias $_.UserName
-Database "Mailbox" -Name $_.UserName –OrganizationalUnit
CorpUsers -Password $password -FirstName $_.FirstName -LastName $_.LastName
-DisplayName "$($_.FirstName) $($_.LastName)" -ResetPasswordOnNextLogon $Right

Аналогично будет и с MS Lync:


Enable-CsUser -Identity "$($_.UserName)@domain.ru" -RegistrarPool "lync.domain.ru" -SipAddress "sip:$($_.UserName)@domain.ru"

Если у вас используются другие решения ? например, Postfix для почты и Asterisk для телефонии, ? на помощь придет возможность подключаться по SSH к *nix серверам с систем Windows. Подробно процедура описана в статье «Перекрестное опыление: управляем Linux из-под Windows, и наоборот». Я же напомню, что запуск команд производится через командлет Invoke-Command:


Invoke-Command -Hostname linux-server -ScriptBlock {some linux commands}

Интереснее дела обстоят с прочими системами, вроде 1С.


Создание пользователя в 1С


Про создание пользователей в 1С: Бухгалтерии при помощи AutoIT я уже писал в статье «Набор отверток администратора 1С». Напомню, что обращаться к 1С «снаружи» удобно при помощи COM-объекта v83.comconnector. Поскольку PowerShell тоже поддерживает COM-объекты, приведу часть скрипта для создания пользователей по-новому:


$obj=new-object -comobject V83.ComConnector
$connect=$obj.Connect("Srvr=""servername"";Ref=""basename"";Usr=""login"";Pwd=""password"";")
#создаем пользователя ИБ
$rights=$connect.Metadata.Roles.find($rght)
$newuser= $connect.ПользователиИнформационнойБазы.createuser()
$newuser.name = "$($surname) $($name)"
$newuser.fullname = "$($surname) $($name) $($fathername)"
$newuser.StandardAuthentication = "False"
$newuser.OSAuthentication="True"
$newuser.OSuser="\\DOMAINNAME\ $($Username)"
$newuser.Roles.add($rights)
$newuser.write()

#создаем пользователя в справочнике "Пользователи"

$bject=$connect.NewObject("СправочникМенеджер.Пользователи")
$newuserS=$bject.CreateItem()
$newuserS.code=$"($surname) $($name)"
$newuserS.Description="$($surname) $($name) $($fathername)"
$newuserS.write()

#Добавляем пользователя в группу

$grp=$connect.Справочники.ГруппыПользователей.НайтиПоНаименованию($group).ПолучитьОбъект()
$t=$grp.ПользователиГруппы.add()
$t.Пользователь = $newuserS.ссылка
$grp.write()

Где $rght ? это права пользователя ИБ, а $group ? нужная группа пользователя. Оба значения берутся из шаблона вместе с ФИО.


Разумеется, точный скрипт будет зависеть от вашей конкретной конфигурации 1С ? не забудьте проконсультироваться с программистом 1С.


Создаем пользователя из 1С


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


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

В случае с 1С можно сделать регулярную выгрузку из базы новых и уволенных сотрудников хоть в том же формате JSON. А дальше уже пусть работает машина. С примером скрипта, обрабатывающего выгрузку в формате CSV можно ознакомиться в статье «Автоматизация кадровых изменений на PowerShell».


Другим вариантом будет запуск регламентных заданий сразу из 1С ? благо 1С тоже довольно богатый возможностями язык.


Например, создание пользователя в AD будет выглядеть так:


Осторожно, код на русском!
Функция СоздатьПользователя(
 Логин,
 ПарольПользователя,
 ОрганизационнаяЕдиница,
 АдресЭлектроннойПочты,
 МенятьПарольПриВходе = Истина,
 Описание,
 ПутьПользователяAD = "",
 SID = "",
 ОписаниеОшибки = ""

) Экспорт
фРезультат  = Истина;

Попытка    
 ОрганизационнаяЕдиницаОбъект = ПолучитьCOMОбъект("LDAP://" + ОрганизационнаяЕдиница);
 ПользовательAD = ОрганизационнаяЕдиницаОбъект.Create("user", "CN=" + Логин);
 ПользовательAD.sAMAccountName        = Логин;
 ПользовательAD.description            = Описание;
 ПользовательAD.userPrincipalName    = Логин + "@" + Константы.НаименованиеДомена.Получить();

 Если Не ПустаяСтрока(АдресЭлектроннойПочты) Тогда
   ПользовательAD.mail                    = АдресЭлектроннойПочты;
 КонецЕсли;

 Если МенятьПарольПриВходе Тогда
   ПользовательAD.pwdLastSet        = 0;

Иначе
   ПользовательAD.pwdLastSet        = -1;
 КонецЕсли;
 ПользовательAD.SetInfo();
 ПользовательAD.SetPassword(ПарольПользователя);

 Исключение
  фРезультат    = Ложь;
  ОписаниеОшибки    = ОписаниеОшибки();
КонецПопытки;

Если фРезультат Тогда
 SID    = ПреобразоватьSID(ПользовательAD.objectSid);
  ПутьПользователяAD    = ПользовательAD.distinguishedName;
 КонецЕсли;

 Если фРезультат Тогда
  ПользовательAD.AccountDisabled = Ложь;
  ПользовательAD.SetInfo();
 КонецЕсли;

 Возврат фРезультат;
КонецФункции

Подробнее с механизмом работы 1С и AD, а также с примерами готовых функций можно ознакомиться в статье «Работа с Active Directory из 1С» на портале «Инфостарт».


А готовы ли вы доверить создание пользователей, пусть и опосредованно, сотрудникам HR?

Комментарии (23)


  1. divanus
    24.04.2018 20:03

    Автоматизация пользователей отличное решение. На это и нужен ИТ, чтобы приказ-юзер-профиль-все права по должности — развертывание всех приложений. И то же при увольнении.


    1. PE4ENEG
      25.04.2018 00:23

      Полностью согласен.
      Было бы ещё интересно увидеть вариацию блокировки уч.записи по письму из outlook.
      И вопрос не совсем в кассу но всё же, есть ли какое либо управление пакетом офисных приложений microsoft office с помощью powershell?


      1. avelor
        25.04.2018 00:45

        Какого рода управление вам нужно?

        А блокировать по письму можно хоть обработчиком почтовым (на сервере ловить нужно письмо от нужного отправителя с нужным содержимым и выполнять скрипт) или макросом в аутлуке…


        1. PE4ENEG
          25.04.2018 00:57

          Первый вариант хорошо работает когда есть доступ к почтовому серверу :)
          Управление да все которое есть, там к примеру поставить автоответ или же сделать полный архив почтового ящика.


          1. avelor
            25.04.2018 01:08

            Смотрите в api, благо у аутлука оно довольно богато. Тут примеров например есть msdn.microsoft.com/en-us/magazine/dn189202.aspx
            А тут описание msdn.microsoft.com/en-us/VBA/Outlook-VBA/articles/object-model-outlook-vba-reference

            Обычно конечно автоответы и архивы делаются на стороне сервера… :)


            1. PE4ENEG
              25.04.2018 07:23

              За ссылки спасибо по изучаю :)
              Ну само собой что на стороне сервера причём одной командой без костылей :)
              Но всё как всегда упирается в доступ к серверам для младших админов, так что приходится крутиться.


  1. zonek
    25.04.2018 00:23

    А дальше?
    Девушка вышла замуж и поменяла фамилию. Необходима изменить уч.запись и все ресурсы на новую фамилию, но что бы все осталось как было.


    1. PE4ENEG
      25.04.2018 00:41

      Ну можно простой скрипт написать на изменение данных для старой учётки.


      1. zonek
        26.04.2018 13:40

        Плюс смена имён сетевых ресурсов, переименование почты, уч. записей в 1с, терминальные профили и т.п.
        Достаточно удобно если все привязано к уч.записи AD. Если системы имеют локальные уч. записи. Это ещё то веселье по автоматизации в крупной компании. Самое забавное если девушка сама уже не помнит куда её предоставлялся доступ.
        В итоге, перенастроив все на новое имя, узнаешь, что девушка уходит в декретный отпуск.
        И на её место приходит новый сотрудник — девушка. И все начинается заново.


    1. avelor
      25.04.2018 00:43

      Переимновать учётку?


      1. PE4ENEG
        25.04.2018 00:54

        Ну тут уже что именно нужно, можно просто display name поменять без всего остального, можно сделать скрипт где будет вызываться комманда на exch сервера с установкой авто ответа и включение переадрессации, и для других служб смотря что именно нужно


  1. Sergey-S-Kovalev
    25.04.2018 06:59

    Как человек который пилит на Powershell в данный момент комплексное решение по синхронизации данных из учетной системы в AD могу сказать, что статья хорошая, но проблема синхронизации AD с учетной системой не раскрывается в статье от слова совсем. Непосредственно создать пользователя, раздать права, доступы и домашние папки это наименьшая из проблем этой автоматизации.

    Основные головняки синхронизации:
    ФИО сотрудников может совпадать и это могут быть разные люди.
    ФИО сотрудников может совпадать и это может быть совмещение.
    При полной выгрузке сотрудников из учетной системы каждый сотрудник может там встречаться от одного до n'оного количества раз, потому что новый табельный номер выдается при смене вида собственности организации, сотрудник мог увольняться и возвращаться в организацию, мог перемещаться по должностям и отделам внутри организации.
    Новая политика создания логинов может ничего не знать про уже существующие логины и почтовые ящики.
    Кадровики ошибаются в написании ФИО. Кадровики могут писать ФИО в том числе и заглавными. У людей может не быть отчества, или отчество может быть двойным…… как и фамилия. А еще сотрудников все могут знать под одним именем, а в кадровой системе у них может быть сходное но фактически другое имя. Наименование отдела или должности сотрудника может превышать длину полей атрибутов Department и Title. Заталкивать табельный номер сотрудника в employeId идея не лучшая, там длина всего 16 байт.
    Есть чисто организационные проблемы: Сотрудники могут числится в одной организации, но в AD должны светить от другой компании.

    И это еще без учета контроля административных и сервисных учетных записей и УЗ внешних компаний подрядчиков.

    И да, для того что бы разгрести все это и не утонуть в ифах, нужны ДКА.

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


    1. PE4ENEG
      25.04.2018 07:19

      Так то оно так конечно, но добавить в скрипт что если такой логин уже есть добавить отчество, или же вообще заставить админа самому логин придумать.А если кто то увольняется само собой не надо удалять учётку просто отключаешь её и в комментарий уволен(а).


      1. Sergey-S-Kovalev
        25.04.2018 07:41

        Вы описываете процесс создания пользователя, опуская процесс непосредственно самой проверки, а тот ли это пользователь. Зная что это тот самый пользователь, создать не сложно. И отключить не сложно. А вот знать точно, это нужно постараться :)


    1. divanus
      25.04.2018 07:20

      Лелаембизнес-процесс утверждения после проверки в отделе кадров. Проверили, все ок? Подписали, утвердили. Грубо пришел Вася в ИТ за ноутом, анкету открыл админ, спросил он, да? :) ОК верифиед. И т.д. так по каждому вопросу.
      Когда компания более 20 человек, то тут действительно на 500-1000 работниках начинают взлетать интересности.
      Кстати, с учетом политической обстановки вот сижу подумываю на никсах реализацию подобную под наш продукт строительный.
      В общем тема горячая, надо обсуждать.


    1. BigD
      25.04.2018 09:14

      а вы не привязывайтесь к табельному номеру. создайте уникальный идентификатор сотрудника, который будет присваиваться всем штаным и нештатным ресурсам, будет сквозным для всех юрлиц, и не будет меняться при приеме/увольнении/переходе/повторном приеме. А к нему уже и привязывайте аккаунты.


      1. Sergey-S-Kovalev
        25.04.2018 09:52

        Ну хорошо, будь по Вашему.
        У меня по штатке три новых сотрудника, и у всех трех полное совпадение по ФИО. Они трудоустроены в один день. При проверке выясняется что у меня уже есть два разных подтвержденных сотрудника полностью совпадающих по ФИО. Итого по штатке пять сотрудников полностью совпадающих по ФИО, но с разными табельными номерами и должностями.
        Как без участия аккаунт админа и специалиста кадровой службы понять сколько учетных записей в итоге должно быть?


        1. BigD
          25.04.2018 10:39

          Я же говорю, HR система при приеме присваивает им уникальный номер. Каждому. Сквозной. Уникальность гарантируется как ручной проверкой, так и, например, использованием последних цифр номера паспорта (как вариант). Далее у вас появляется отчет/выгрузка, в которой видны идентификаторы, ФИО, табельные. И дублей нет.


          1. avelor
            25.04.2018 11:52

            а может использовать сразу SID? :)


            1. BigD
              25.04.2018 16:38

              SID — это один из атрибутов ИТ систем (вторичный), а уникальный идентификатор человека — это HR атрибут (первичный)


          1. Sergey-S-Kovalev
            25.04.2018 12:06

            В случае с 1С — это изменения в типовой конфигурации. Такие изменения приводят к снятии конфигурации с поддержки. Добавим к этому гремучую разношерстность организаций размером от мала до велика, включая версионность и тем что иногда даже не известно, кто обслуживает ЗуП. Все чего удается добиться, это стандартизованная выгрузка информации по всем сотрудникам с их статусами.

            Но это все фигня, поскольку, связка табельного и именования организации уже обеспечит ту самую, пока я не понял зачем, сквозную уникальность. Но это не решает проблемы с пятью полными ФИОшниками, а в разрезе нескольких организаций это даже обостряет проблему, поскольку один человек может работать в нескольких организациях одновременно, и эти организации могут быть в одном домене AD.


            1. BigD
              25.04.2018 16:40

              табельные-то будут разными в разных юрлицах. это не сквозной идентификатор.

              поэтому нужен один «над ними». Так и работают системы identity management.