Я считал, что неплохо разбираюсь в powershell, но мне никогда не приходилось работать с учетными данными пользователей. Однако сейчас я в поиске работы и на одном из собеседований мне поставили тестовое задание написать скрипт, который должен был:
- Проверить наличие и статус (включена/отключена) учетной записи пользователя.
- Проверить включена ли учетная запись в группу «Администраторы»
- Если учетная запись отсутствует, то создать учетную запись и добавить ее в группу администраторы, проставить флаги «Запретить смену пароля пользователем» и «Срок действия пароля не ограничен»
- Если учетная запись существует, но отключена либо не входит в группу «Администраторы», то включить учетную запись и добавить ее в группу «Администраторы», проставить флаги «Запретить смену пароля пользователем» и «Срок действия пароля не ограничен»
- Скрипт не должен зависеть от языка операционной системы.
Я подумал, что ничего сложного и первым делом решил проверить есть пользователь Admin на моем компьютере. Недолго думая, я вбил команду:
Get-User admin
И тут же получил ошибку
Get-User : Имя "Get-User" не распознано как имя командлета, функции, файла сценария или выполняемой программы.
Немного опешив, от того, что такая полезная команда и не распознала я погуглил и обнаружил, что команда Get-User работает только в консоли Powershell для Exchange. Для работы с локальными пользователями необходимо использовать Get-Localuser, а для доменных Get-Aduser. Осознав свою ошибку, я вбил:
Get-Localuser admin
И получил ответ
Name Enabled Description
---- ------- -----------
Admin True Встроенная учетная запись администратора компьютера/домена
Ну теперь проверить есть пользователь или нет, не составит большого труда, однако и тут меня ждал очередной подвох. Через условный оператор if else сделать это оказалось не так-то просто.
Дело в том, что если пользователь есть в системе, то на выход мы получаем не значение true, а целый набор данных, с именем, описанием пользователя, включена эта учетная запись или нет. А если пользователя нет, то powershell выдает ошибку. Побродив по просторам интернета, я обнаружил, что для этих целей лучше использовать оператор try сatch.
$user = 'admin'
try {
Get-LocalUser $user -ErrorAction Stop | Out-Null
write-host пользователь $user есть -foregroundcolor Green
}
Catch {
write-host пользователя $user нет -foregroundcolor Red
}
Я добавил переменную $user, чтобы было проще менять имена пользователя во всем скрипте. ErrorAction Stop необходим, чтобы скрипт не прервался на этом шаге из-за ошибки. Знак | разделяет шаги конвейера, а Out-Null скроет вывод текста ошибки. Так же я добавил вывод текста с подсветкой, для удобства проверки скрипта.
Далее я захотел проверить, включена или отключена учетная запись. Как я уже говорил, команда Get-LocalUser выдает целый набор данных и для проверки, мне нужно было выделить только один параметр Enabled со значением true или false. Для этого я воспользовался следующей командой:
(Get-LocalUser $user).enabled
Убедившись, что он работает, я сделал следующую проверку и добавил команду включения пользователя.
$user = 'admin'
if ((Get-LocalUser $user).enabled -eq "True") {
write-host учетная запись включена -foregroundcolor Green
}
else {
write-host учетная запись отключена -foregroundcolor Red
Enable-LocalUser $user
write-host учетная запись включена -foregroundcolor Green
}
Для включения пользователя, естественно необходимо запускать консоль под правами администратора.
Во втором пункте задания, необходимо было определить входит ли пользователь в группу администраторов. Для проверки наличия пользователя в той или иной группе есть команда Get-LocalGroupMember. Однако имя группы администраторов, меняется от языка операционной системы. Поэтому мне пришлось воспользоваться стандартным SID S-1-5-32-544. Проверку я также сделал через try сatch.
$user = 'admin'
try {
Get-LocalGroupMember -SID S-1-5-32-544 -Member $user -ErrorAction Stop | Out-Null
write-host пользователь $user состоит в группе администраторы -foregroundcolor Green
}
Catch {
write-host пользователь $user не состоит в группе администраторы -foregroundcolor Red
Add-LocalGroupMember -SID S-1-5-32-544 -Member $user
write-host пользователь $user состоит в группе администраторы -foregroundcolor Green
}
В случае, если пользователь не состоит в группе, администраторов он будет в нее добавлен.
На следующем этапе, у меня стояла задача определить отключена настройка смены пароля у пользователя или нет. Тут я наткнулся на очередные подводные камни. Дело в том, что если у пользователя, срок действия пароля не ограничен, то параметр PasswordExpires не выдает никаких значений. А если эта галочка отключена, то у разных пользователей будет стоять разная дата смены пароля. Выход из этого положения я всё-таки придумал:
if ((Get-LocalUser $user).PasswordExpires -eq $null) {
write-host срок действия паролья не ограничен -foregroundcolor Green
}
else {
write-host срок действия пароля ограничен -foregroundcolor Red
set-LocalUser $user -PasswordNeverExpires:$true
write-host срок действия пароля не ограничен -foregroundcolor Green
}
Дальше мне было необходимо создавать пользователя. Я никак не ожидал, что и здесь меня может ждать подвох. При создании пользователя командой
new-LocalUser -User $user -password P@ssW0rD!
Возвращается ошибка:
Не удается привязать параметр "Password". Не удается преобразовать значение "P@ssW0rD!" типа "System.String" в тип "System.Security.SecureString".
Дело в том, что параметр -password должен использовать SecureString, вместо обычной текстовой строки. Для этого я сделал переменную $password и сконвертировал её в securestring.
$password = convertto-securestring "P@ssW0rD!" -asplaintext -force
А сам скрипт по созданию пользователя и добавления его в группу администраторов
new-LocalUser -User $user -password $password -PasswordNeverExpires:$true -AccountNeverExpires:$true
Add-LocalGroupMember -SID S-1-5-32-544 -Member $user
Готовый скрипт учитывающий все условия у меня получился таким образом:
$user = 'admin'
$password = convertto-securestring "P@ssW0rD!" -asplaintext -force
try {
Get-LocalUser $user -ErrorAction Stop | Out-Null
cls
write-host пользователь $user есть -foregroundcolor Green
if ((Get-LocalUser $user).enabled -eq "True") {
write-host учетная запись включена -foregroundcolor Green
}
else {
write-host учетная запись отключена -foregroundcolor Red
Enable-LocalUser $user
write-host учетная запись включена -foregroundcolor Green
}
if ((Get-LocalUser $user).PasswordExpires -eq $null) {
write-host срок действия паролья не ограничен -foregroundcolor Green
}
else {
write-host срок действия пароля ограничен -foregroundcolor Red
set-LocalUser $user -PasswordNeverExpires:$true
write-host срок действия паролья не ограничен -foregroundcolor Green
}
try {
Get-LocalGroupMember -SID S-1-5-32-544 -Member $user -ErrorAction Stop | Out-Null
write-host пользователь $user состоит в группе администраторы -foregroundcolor Green
}
Catch {
write-host пользователь $user не состоит в группе администраторы -foregroundcolor Red
Add-LocalGroupMember -SID S-1-5-32-544 -Member $user
write-host пользователь $user состоит в группе администраторы -foregroundcolor Green
}
}
Catch {
cls
write-host пользователя $user нет -foregroundcolor Red
new-LocalUser -User $user -password $password -PasswordNeverExpires:$true -AccountNeverExpires:$true
Add-LocalGroupMember -SID S-1-5-32-544 -Member $user
write-host пользователь $user создан и добавлен в группу администраторов -foregroundcolor Green
}
Post Scriptum
Однако хранение пароля администратора в скрипте — это не лучшая практика с точки зрения безопасности. Для этого можно использовать хэш пароля, а не сам пароль.
$user = 'admin1'
$hash = "01000000d08c9ddf0115d1118c7a00c04fc297eb0100000048baf1b47a72d845b4eeda8659da9fd70000000002000000000010660000000100002000000004d2a3bf03aac92c2e172dc002d1fe8759da4655850462aface5c25f52921e05000000000e8000000002000020000000bfa652b6f7cc6845e3cee1831b54ab93dc272d0b2203024c3de8bc4789a2698a10000000923fb50dcf01125913534d0c1ba6d827400000002757df7d8a8b39c8e84b81323acff1d72419580a0022cf610926e5f081a2e895320088d482eb407f8157aad82f091abee7427b357e871d12238a8f74131238e7"
$hash
$password = ConvertTo-SecureString -String $hash
$password
new-LocalUser -User $user -password $password -PasswordNeverExpires:$true -AccountNeverExpires:$true
Add-LocalGroupMember -SID S-1-5-32-544 -Member $user
Для того, чтобы получить хэш пароля можно воспользоваться следующим скриптом
$Secure = Read-Host -AsSecureString
$Secure
$hash = ConvertFrom-SecureString -SecureString $Secure
$hash
Который запросит ввод пароля с клавиатуры.
И маленький бонус для вывода всех отключенных записей
Get-LocalUser | Where-Object {$_.enabled -eq $false}
Надеюсь, потраченное мною время поможет кому-то в работе. Да и для себя будет полезно не забыть этот бесценный опыт.
Автор: Daysleeper