No dobra. Do włączenia remotingu na serwerze lokalnym służy polecenie
Enable-PSRemoting
Niestety to polecenie nie ma parametru -ComputerName, aby włączyć remoting na systemie zdalnym 🙁
Na szkoleniu Powershell dla administratorów Windows pokazuję, że jeśli chcesz włączyć remoting na maszynie zdalnej, to powinieneś wykorzystać zasady grupy i stosując te zasady do serwerów konfigurować je do włączenia lub wyłączenia remotingu. A co jeśli w firmie konfiguracją domeny zajmuje się ktoś inny!? Nie masz z nim kontaktu, a nawet jeśli masz to nie masz mocy przekonania kolegów o tym, że potrzebujesz włączenia remotingu. Hmmm….
Do zdalneo uruchomienia polecenia można się też posłużyć poleceniem Invoke-WMIMethod. Gdyby tak tej komencie przesłać instrukcję:
powershell.exe -command „{Enable-PSRemoting -Force}”
to cel byłby osiągnięty! Tylko jest jeden problem… Invoke-WMIMethod uruchomi polecenie nie dołączając tokenu administratora (nie jako administrator – elevated). Tymczasem Enable-PSRemoting musi być uruchamiane jako administrator!
Trzeba pokombinować. Jest metoda, która pozwala na sytemie zdalnym uruchmić polecenie jako administrator. Możesz utworzyć zadanie w harmonogramie zadań, do uruchomienia na koncie system i natychmiast to zadanie uruchomić. W zadaniu możesz zdefiniować do uruchomienia właśnie powershella włączającego Remoting!
Takie rozwiązanie proponuje książka Windows Powershell Cookboook. Oto i ono po moich małych przeróbkach Enable-PSRemotingRemotely.txt. A tu parę słów komentarza:
Chcemy pracować z funkcją, a nie skryptem, więc dodajemy nagłówek:
function Enable-PSRemotingRemotely() { param( ## The computer on which to enable remoting $Computername, ## The credential to use when connecting $Credential = (Get-Credential) )
Za chwilę będzie dość złożony tekst z komendami zawierający w sobie kolejne komendy, warto więc włączyć tzw. Strict Mode, który powoduje, że gdy odwołasz się do niezainicjowanej zmiennej to będzie błąd. Bardzo dobry krok w skomplikowanych skryptach!
Set-StrictMode -Version Latest $VerbosePreference = "Continue"
W kolejnych krokach czasami trzeba skorzystać z credentials, czasami z nazwy użytkownika, a czasami z hasła. Przygotowujemy zmienne:
$credential = Get-Credential $credential $username = $credential.Username $password = $credential.GetNetworkCredential().Password
Teraz konstruujemy skrypt, który przez Invoke-WMIMethod będzie uruchamiany na zdalnym systemie. Wszystkie pracujące tu komendy będą już działać lokalnie na tamtym systemie.
$script = @" `$log = Join-Path `$env:TEMP Enable-RemotePsRemoting.output.txt `$scriptFile = Join-Path `$env:TEMP tmpScriptFile.ps1 Remove-Item -Force `$log -ErrorAction SilentlyContinue Remove-Item -Force `$scriptFile -ErrorAction SilentlyContinue Start-Transcript -Path `$log ## Create a task that will run with full network privileges. ## In this task, we call Enable-PsRemoting 'Enable-PSRemoting -Force' | Out-File `$scriptFile -Force
schtasks /CREATE /TN 'Enable Remoting' /SC WEEKLY /RL HIGHEST /RU SYSTEM /TR "powershell.exe -executionpolicy bypass -command `$scriptFile" /F | Out-String schtasks /RUN /TN 'Enable Remoting' | Out-String `$securePass = ConvertTo-SecureString $password -AsPlainText -Force `$credential = New-Object Management.Automation.PsCredential $username,`$securepass ## Wait for the remoting changes to come into effect for(`$count = 1; `$count -le 10; `$count++) { `$output = Invoke-Command localhost { 1 } -Cred `$credential -ErrorAction SilentlyContinue if(`$output -eq 1) { Write-Host "Done!!!"; break; } Write-Host "Attempt `$count : Not ready yet.`n" Sleep 5 } ## Delete the temporary task schtasks /DELETE /TN 'Enable Remoting' /F | Out-String Stop-Transcript "@
uff… długie to było a co się tam nie działo:
- tworzymy zmienne na nazwy plików tymczasowych. Wszystkie będą tworzone w profilu użytkownika (odwołanie do $env:temp)
- Plik log będzie zawierał log z działania skryptu
- a plik scriptFile zawiera skrypt, w którym znajdzie się polecenie włączające remoting
- dwa polecenie SCHTASKS po pierwsze tworzą zadanie w harmonogramie, a po drugie uruchamiają to zadanie. Opis schtasks znajdziesz na msdn
- Pętla for spowalnia skrypt, czekając aż uda się nawiązać połączenie z localhost przez remoting (tak z localhost, bo polecenia są uruchamiane na systemie lokalnym)
- Na zakończenie zadanie z harmonogramu będzie usunięte i zatrzymamy logowanie. Plik można przejrzeć w celu debuggownaia.
No dobrze. Skrypt już jest gotowy, teraz chcemy go wysłać i wykonać na systemie zdalnym. Dlatego konwertujemy skrypt do postaci Base64.
$commandBytes = [System.Text.Encoding]::Unicode.GetBytes($script) $encoded = [Convert]::ToBase64String($commandBytes)
Teraz wystarczy dokleić zakodowany skrypt do polecenia powershell.exe i uruchomić ten skrypt na maszynie zdalnej przez Invoke-WMIMethod:
Write-Verbose "Configuring $computername" $command = "powershell -NoProfile -EncodedCommand $encoded" $null = Invoke-WmiMethod -Computer $computername -Credential $credential ` Win32_Process Create -Args $command
Teraz wszystko w rękach powershella. Na dodatek wykonanie zadania w harmonogramie zadania odbywa się asynchronicznie, tzn naszy skrypt przechodzi do kolejnych kroków, a zadanie jeszcze nie zdążyło się wykonać na serwerze. Dlatego jeszcze raz dodajemy pętelkę for, która będzie sprawdzać, czy remoting już działa. Jeśli wszystko jest ok, to w ostatnim kroku wyświetli informacje o maszynie zdalnej:
## Wait for the remoting changes to come into effect for($count = 1; $count -le 10; $count++) { $output = Invoke-Command $Computername { 1 } -Cred $credential -ErrorAction SilentlyContinue if($output -eq 1) { Write-Host "Done!!!"; break; } Write-Host "Attempt $count : Not ready yet." Sleep 5 } Write-Verbose "Testing connection" Invoke-Command $computername { Get-WmiObject Win32_ComputerSystem } -Credential $credential
}
Komentarze:
[…] Często pojawiające się pytanie, to czy remoting może być włączony zdalnie i to najlepiej przez jakąś komendę w powershellu. Odpowiedź wydaje się oczywista: NIE! Ale czy na pewno? Jak sugeruje tytuł kolejnego wpisu, chyba jednak powinno się udać! Ja używam tej metody produkcyjnie i u mnie działa. Proste to nie jest, wymaga kilku sztuczek, ale o prawie wszystkich mówimy na naszym kursie, więc jeśli już kończysz materiał – nie powinno być z tym problemu. Powershell: Włączenie remotingu z maszyny zdalnej. Niemożliwe? Wcale nie! […]