Сохранение переменных пользовательской среды в сценарии входа в Powershell с правами администратора

Я случайно удалил 180 пользователей из своего AD, и их нельзя восстановить. Я воссоздал учетные записи в AD, а что нет. Это создает новый профиль на их ноутбуках, когда они входят в систему из-за нового SID. Я пытаюсь написать сценарий, который предоставляет им доступ к папке их старого профиля и создает ярлык на рабочем столе, ведущий туда.

У меня скрипт работает нормально с одной проблемой. Используемые переменные среды в конечном итоге ссылаются на учетную запись администратора, которая запускает сценарий. Сами пользователи не имеют права изменять безопасность своей старой папки. Мне нужно попытаться сделать так, чтобы переменные среды ссылались на пользователя, но при этом иметь привилегию учетной записи администратора для перезаписи разрешений.

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

$permission = ":(OI)(CI)M"
$sam = $env:USERNAME
$folderName = "C:\Users\$($sam)"

Invoke-Expression -Command ( 'ICACLS $folderName /grant:r $sam$($permission) /t' )

$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$Home\Desktop\Profile Backup.lnk")
$Shortcut.TargetPath = $folderName
$Shortcut.Save()

Меня беспокоят переменные $env:USERNAME и $home.

Или есть другой способ, которым я должен решать эту проблему?


person MagicMatt    schedule 28.03.2018    source источник
comment
Какова текущая папка пользователя по сравнению со старым именем папки? Им потребуются административные привилегии, если вы не укажете их SID в команде.   -  person Maximilian Burszley    schedule 28.03.2018
comment
Таким образом, старое имя папки будет их именем пользователя, т.е. charlie. Имя новой папки — charlie.domain. Поэтому, чтобы переделать разрешения, им нужны права администратора, что является моей проблемой. Чтобы автоматизировать все это с помощью сценариев, мне нужно использовать переменные среды в сценарии, чтобы указать на правильную папку, создать ярлык и т. д. Проблема в том, что запуск сценария с правами администратора приводит к тому, что переменные среды разрешаются в учетную запись администратора, для Например, $home будет преобразован в C:\Users\Administrator вместо C:\Users\charlie. И $env:USERNAME разрешается в Aministrator.   -  person MagicMatt    schedule 29.03.2018
comment
@MagicMatt Я несколько неправильно понял контекст. Я улучшил свой ответ в PowerShell. Посмотрим, поможет ли это тебе.   -  person tukan    schedule 29.03.2018


Ответы (2)


Вы можете использовать команду query session для получения логина текущего вошедшего в систему пользователя. Затем создайте объект NTAccount на основе этого, чтобы получить объекты SID и win32_userprofile WMI, чтобы узнать путь к профилю. Как это:

$m = query session | Select-String -Pattern "\>console\s*(\S*)\s"
$sam = $m.Matches[0].Groups[1].value

$acc = New-Object System.Security.Principal.NTAccount($sam)
$sid = $acc.Translate([System.Security.Principal.SecurityIdentifier]).Value

$profile = Get-CimInstance -ClassName win32_userprofile -Filter "SID='$sid'"
$folderName = $profile.LocalPath
person Janne Tuukkanen    schedule 29.03.2018
comment
Спасибо, похоже, это именно то, что я ищу, у меня будет возможность протестировать на следующей неделе или двух. Я дам вам знать, как я иду. - person MagicMatt; 30.03.2018
comment
Спасибо!! Это сработало очарование! Именно то, что я искал. Мне пришлось внести одну небольшую корректировку в ваш фильтр сеанса запроса, так как «›» менялся местами при выполнении под учетной записью SYSTEM во время запланированного задания. Вот изменения, которые я сделал: $m = query session | Консоль Select-String -Pattern\s*(\S*)\s - person MagicMatt; 09.04.2018

Изменить Я еще раз подумал об этом за ночь, поэтому я обновлю ответ. Вам потребуется зашифровать пароль администратора домена, после чего пользователи будут запускать скрипт.

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

На первом этапе администратор домена должен зашифровать свой пароль в файле:

Это должно быть подготовлено администратором домена (распространяется вместе со сценарием PS) — я рекомендую сменить пароль после завершения восстановления:

1) Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File 'C:\<script_path>\admin_passwd.txt'

2) Это должно выполняться пользователем (вы должны ввести идентификатор пользователя-администратора и получить файл паролей, распространяемый вместе со сценарием). Путь к скрипту можно получить с помощью (Get-Location).Path. Я не добавляю его в исходный код, поэтому вы сами можете решить, как его реализовать:

$permission = ":(OI)(CI)M"
$admin= "<your_admin_userid>"
$sam = $env:USERNAME
$domain = $env:UserDomain
$folderName = "C:\Users\$($sam)"

# get domain admin password
$encrypted_passwd = get-content 'C:\<script_path>\admin_passwd.txt' | ConvertTo-securestring

# Setting process invocation parameters.
$process_start_info = New-Object -TypeName System.Diagnostics.ProcessStartInfo
$process_start_info.CreateNoWindow = $true
$process_start_info.UseShellExecute = $false
$process_start_info.RedirectStandardOutput = $true
$process_start_info.RedirectStandardError = $true
$process_start_info.UserName = $admin
$process_start_info.Domain = $domain
$process_start_info.Password = $encrypted_passwd
$process_start_info.Verb = 'runas'
$process_start_info.FileName = 'ICACLS'
$process_start_info.Arguments = "$folderName /grant:r $sam$($permission) /t"

# Creating process object.
$process = New-Object -TypeName System.Diagnostics.Process
$process.StartInfo = $process_start_info

# Start the process
[Void]$process.Start()

$process.WaitForExit()

# synchronous output - captures everything
$output = $process.StandardOutput.ReadToEnd()
$output += $process.StandardError.ReadToEnd()

Write-Output $output


$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$Home\Desktop\Profile Backup.lnk")
$Shortcut.TargetPath = $folderName
$Shortcut.Save()
person tukan    schedule 28.03.2018
comment
Спасибо tukan за ответ и решение. Проблема здесь заключается в том, что у самого пользователя нет необходимого разрешения для внесения изменений в папку. Единственными людьми, имеющими право изменять разрешения, являются группа локальных администраторов и администраторы домена. Этот метод как-то обходит это? - person MagicMatt; 28.03.2018
comment
@MagciMatt нет, этот скрипт не обходит это ограничение. Не могли бы вы перечислить свою политику выполнения? Get-ExecutionPolicy -List - person tukan; 28.03.2018
comment
@MagicMatt, у вас также может быть чрезвычайная ситуация, и вы можете сделать пользователей временными локальными администраторами. - person tukan; 28.03.2018
comment
Почему вы используете класс Process вместо простого использования Start-Process.. и передача учетных данных не имеет смысла, как и бизнес ICACLS, учитывая, что это рабочий стол пользователя, и у них нет доступа к другой папке. - person Maximilian Burszley; 28.03.2018
comment
@ TheIncorrigible1, ты был частично прав. Если он находится на рабочем столе пользователя, необходим другой подход. Я использую System.Diagnostics.Process из-за изменения контекста безопасности (домена). Если вы можете это сделать Start-Process, пожалуйста, покажите мне свой код. - person tukan; 29.03.2018
comment
@MagicMatt теперь скрипт заполнит данные пользователя с правами администратора. - person tukan; 29.03.2018