PowerShell 1.0 в корпоративном AD: 400 пользователей из CSV за три минуты
Первый production-скрипт на PowerShell 1.0: массовое создание учёток AD из HR-выгрузки. Переводим плановые задачи с VBScript - и не жалеем.
PowerShell 1.0 выпущен для Windows XP и Server 2003 в конце 2006 года и начинает массово применяться в корпоративных Windows-средах
В ноябре мы переписали три плановых скрипта на PowerShell и зафиксировали: VBScript - в архив. Прошло четыре месяца. Пришёл момент, который проверил это решение на прочность.
HR-отдел клиента провёл реорганизацию. Новое юрлицо, новый домен, перевод сотрудников. Задача: создать учётные записи в AD для нескольких сотен человек. Файл - CSV из HR-системы, поля стандартные: имя, фамилия, отдел, должность, логин, временный пароль. Дедлайн - к началу следующей рабочей недели.
Раньше это был бы полный рабочий день: открыть ADUC, кликнуть «New User», заполнить поля, назначить группы, повторить. При хорошем темпе - сорок-пятьдесят учёток в час. Плюс ошибки: опечатки в логинах, пропущенные группы, забытый флаг «сменить пароль при первом входе».
Скрипт
Нативных командлетов New-ADUser в PowerShell 1.0 нет - появились позже в отдельном модуле. Работаем через ADSI, как и в ноябре. Код читается нормально, логика прозрачная:
Import-Csv "C:\Input\new-users.csv" -Encoding UTF8 | ForEach-Object {
$ouPath = "OU=$($_.Department),OU=Users,DC=company,DC=local"
$ou = [ADSI]"LDAP://$ouPath"
$newUser = $ou.Create("user", "CN=$($_.LastName) $($_.FirstName)")
$newUser.Put("sAMAccountName", $_.Login)
$newUser.Put("userPrincipalName", "$($_.Login)@company.local")
$newUser.Put("givenName", $_.FirstName)
$newUser.Put("sn", $_.LastName)
$newUser.Put("department", $_.Department)
$newUser.Put("title", $_.Title)
$newUser.Put("pwdLastSet", 0) # смена пароля при первом входе
$newUser.SetInfo()
$newUser.SetPassword($_.TempPassword)
$newUser.InvokeSet("AccountDisabled", $false)
$newUser.SetInfo()
Write-Host "OK: $($_.Login)"
}
Запустили. Терминал начал бодро печатать OK: строчками. Через несколько минут - готово. Все записи в нужных OU, пароли установлены, флаг смены пароля проставлен.
Что было дальше - небольшой сюрприз. Около десятка строк упали с ошибкой: OU для нескольких отделов не существовало - новая оргструктура, HR завёл подразделения, которых ещё не было в AD. Скрипт это поймал и выдал явный стектрейс, что позволило быстро найти проблемные записи, создать OU вручную и перезапустить только для них. Без скрипта это бы потерялось в ручном потоке и вылезло уже как жалоба от пользователя.
Что изменилось по сравнению с ноябрём
В ноябрьском варианте скрипт создания пользователей был демонстрационным - принимал один CSV, работал линейно, падал при первой ошибке. Этот - production. Несколько доработок, которые пришлось добавить по ходу:
- Проверка существования OU перед созданием. Если OU нет - пишем в отдельный лог-файл и продолжаем. Не останавливаем весь батч из-за одной проблемной записи.
- Проверка существования логина через поиск по
sAMAccountName. Дубликаты в HR-файле встречаются - особенно при переводах, когда человек уже есть в системе. - Запись результата в выходной CSV: кому создали, кому нет и почему. Отдаём HR-отделу как отчёт.
Это примерно ещё двадцать строк кода. Итого скрипт на шестьдесят строк делает то, что раньше занимало полный день руками двух человек.
Переводим плановые задачи
После этого прогона договорились внутри команды: всё, что запускается по расписанию или выполняется чаще одного раза, - пишется на PowerShell. VBScript - только если скрипт уже существует и работает, и переписывать его нет смысла. Новый VBScript не пишем.
В очереди на перевод:
- Генерация отчётов по просроченным учёткам. Сейчас - ADSI через VBScript, сто строк, хрупко.
- Управление группами рассылки Exchange. Там своя история с COM-объектами, которые в PowerShell чуть удобнее.
- Ежемесячный экспорт членов привилегированных групп для аудита. Это вообще должно было быть автоматизировано давно.
PowerShell 1.0 устанавливается отдельным пакетом - не входит в дистрибутив Server 2003. Мы добавили его в стандарт ввода серверов в эксплуатацию в рамках сопровождения: без PowerShell сервер управления считается неполным. На остальных серверах - по необходимости. Execution Policy - RemoteSigned везде: локальные скрипты без подписи, сетевые - только подписанные.
Один момент, который стоит упомянуть: Import-Csv с кириллическими данными без явного -Encoding UTF8 может удивить. HR-файл пришёл в UTF-8, и без параметра кодировки имена выглядели как мусор. Добавили ключ - и порядок. Мелочь, но в три часа дня пятницы перед дедлайном это не мелочь.