Problem with Remote Powershell ps1 execution - powershell

Today I have same issue and I cannot find solution, search in WEB read ton articles but without success.
My problem with running PowerShell script on remote machine.
If I run this script locally – it’s works, but remote not.
This is my full story.
Server:
Windows 2008 R2 with SP1 + latest updates
FW – Off
UAC – ON :
- User Account Control: Use Admin Approval Mode for the built-in Administrator account – Disable
- User Account Control: Allow UIAccess applications to prompt for elevation without using the secure desktop. – Disable
- User Account Control: Behavior of the elevation prompt for administrators in Admin Approval Mode – Elevate without prompting
- User Account Control: Detect application installations and prompt for elevation – Disable
Domain: hardening.com
Hostname: qwerty12345
Version of PowerShell is Installed:
PS C:\Windows\system32> $PSVersionTable
Name Value
---- -----
CLRVersion 2.0.50727.5420
BuildVersion 6.1.7601.17514
PSVersion 2.0
WSManStackVersion 2.0
PSCompatibleVersions {1.0, 2.0}
SerializationVersion 1.1.0.1
PSRemotingProtocolVersion 2.1
Client:
Windows 2008 R2 + latest updates
FW – Off
UAC – ON :
- User Account Control: Use Admin Approval Mode for the built-in Administrator account – Disable
- User Account Control: Allow UIAccess applications to prompt for elevation without using the secure desktop. – Disable
- User Account Control: Behavior of the elevation prompt for administrators in Admin Approval Mode – Elevate without prompting
- User Account Control: Detect application installations and prompt for elevation – Disable
Domain: systemqa.com
Version of PowerShell is Installed:
PS C:\> $PSVersionTable
Name Value
---- -----
CLRVersion 2.0.50727.4952
BuildVersion 6.1.7600.16385
PSVersion 2.0
WSManStackVersion 2.0
PSCompatibleVersions {1.0, 2.0}
SerializationVersion 1.1.0.1
PSRemotingProtocolVersion 2.1
• On Client installed also PowerCLI
1. On Server , I have file "C:\Windows\Temp\ ConfigurationWinRM.ps1” with following content:
winrm set winrm/config/client `#`{TrustedHosts=`"`*`"`}
winrm set winrm/config/winrs '#{MaxShellsPerUser="100"}'
2. My mission run those script on remote “Server” machine.
3. I run following script from “Client” machine but get always same errors:
Message = Access is denied.
Error number: -2147024891 0x80070005
a. Example 1:
$domainCrd = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "$domainUser#$domainNameFQDN",$domainPASS
$ComputerName = "qwerty12345.hardening.com"
invoke-command -ComputerName $ComputerName -Credential $domainCrd -ScriptBlock {
$FileName = "ConfigurationWinRM.ps1"
$ItemLocation = "C:\Windows\Temp\"
powershell -NoProfile -Command ". $ItemLocation$FileName"
}
b. Example 2:
$ComputerName = "qwerty12345.hardening.com"
$securePassword = ConvertTo-SecureString "**********" -AsPlainText -force
$credential = New-Object System.Management.Automation.PsCredential("$domainName\$domainUser",$securePassword)
Invoke-Command -ComputerName $ComputerName -ScriptBlock {
$FileName = "ConfigurationWinRM.ps1"
$ItemLocation = "C:\Windows\Temp\"
powershell -Command ". $ItemLocation$FileName"
} -Credential $credential
c. Example 3:
[ScriptBlock] $global:runFile = {
$FileName = "ConfigurationWinRM.ps1"
### $ItemLocation = "C:\Windows\Temp\"
$ItemLocation = "$env:windir\Temp\"
& "$ItemLocation$FileName"
}
RemotePowerShellConnect domain $runFile
WSManFault
+ CategoryInfo : NotSpecified: (WSManFault:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
Message = Access is denied.
Error number: -2147024891 0x80070005
Access is denied.
WSManFault
Message = Access is denied.
Error number: -2147024891 0x80070005
Access is denied.
[vSphere PowerCLI] C:\> $error[0] | Format-List * -Force
PSMessageDetails :
OriginInfo : qwerty12345.hardening.com
Exception : System.Management.Automation.RemoteException:
Error number: -2147024891 0x80070005
Access is denied.
TargetObject :
CategoryInfo : NotSpecified: (:) [], RemoteException
FullyQualifiedErrorId : NativeCommandErrorMessage
ErrorDetails :
InvocationInfo :
PipelineIterationInfo : {}
d. Example 4:
[vSphere PowerCLI] C:\> [ScriptBlock] $global:www = {
$FileName = "ConfigurationWinRM.ps1"
$ItemLocation = "C:\Windows\Temp\"
function Invoke-Admin() {
param ( [string]$program = $(throw "Please specify a program" ),
[string]$argumentString = "",
[switch]$waitForExit )
$psi = new-object "Diagnostics.ProcessStartInfo"
$psi.FileName = $program
$psi.Arguments = $argumentString
$psi.Verb = "runas"
$proc = [Diagnostics.Process]::Start($psi)
if ( $waitForExit ) {
$proc.WaitForExit();
}
}
Write-Host -ForegroundColor Green "Invoke-Admin powershell $ItemLocation$FileName"
Invoke-Admin powershell $ItemLocation$FileName
}
[vSphere PowerCLI] C:\> RemotePowerShellConnect domain $www
Session state: Opened
Session availability: Available
Running
Service is running ...
You connect to VM Remote PowerShell ...
Invoke-Admin powershell C:\Windows\Temp\ConfigurationWinRM.ps1
[vSphere PowerCLI] C:\>
[vSphere PowerCLI] C:\>
Nothing heppend !!!!! No updates on remote “Server” machine !!!
e. Example 5:
.\tmp\psexec -d \\$hostNAME -u $domainName\$domainUser -p $myPASS cmd /C START /WAIT powershell %windir%\Temp\ConfigurationWinRM.ps1
PsExec v1.98 - Execute processes remotely
Copyright (C) 2001-2010 Mark Russinovich
Sysinternals - www.sysinternals.com
cmd started on qwerty12345 with process ID 3860.
[vSphere PowerCLI] C:\>
Nothing heppend !!!!! No updates on remote “Server” machine !!!

Am I correct in reading that there is just one script file, only on the local server, and not on any of the remote clients?
If that's the case, then I think you should try this syntax:
$FileName = "ConfigurationWinRM.ps1"
$ItemLocation = "C:\Windows\Temp\"
Invoke-Command -ComputerName $ComputerName -filepath "$ItemLocation$FileName" -cred $credential
I think what's happening when you use the scriptblock syntax is:
scriptblock defined on local machine, encapsulated as an object
scriptblock object passed to each remote machine
scriptblock executed verbatim on the remote machine, therefore it's looking for your script file on the remote machine at c:\windows\temp (it doesn't exist so it's throwing some BS access denied error)
Based on the help info the filepath parameter, using -filepath will do the following instead:
read in script file locally, convert
contents to a scriptblock object
scriptblock object passed to each
remote machine
scriptblock executed verbatim on the
remote machine, no references to the
.ps1 file at all at this point

Related

Set-Service : A parameter cannot be found that matches parameter name 'Credential'

I am trying to use a powershell script to change the login credential of a service. As per this Microsoft documentation (example 8), I am using the following code:
$credential = Get-Credential
Set-Service -Name serviceName -Credential $credential
When I run the script, I am prompted for a username and password, which I enter, but then the following error results:
Set-Service : A parameter cannot be found that matches parameter name 'Credential'.
At line:2 char:28
+ Set-Service -Name serviceName -Credential $credential
+ ~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-Service], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.SetServiceCommand
What might be causing this? This machine is not on a domain, but I am logged on as a local administrator, and running powershell as an administrator. I have permissions to change these services and can enter the login details normally via the usual Services GUI.
The Credential parameter only exist for PowerShell version 6+ (which is out of support).
Probably you are using a version from before PowerShell 6 (most probably 5.1 which is still the main version in Windows 10 and 11).
See below Set-Service in:
PowerShell 5.1
PowerShell 6.0 (Archive)
PowerShell 7.0
Run $PSVersionTable.PSVersion, to your PowerShell version.
If you run (Get-Help -Name Set-Service).Parameters.parameter.Name, you'll find all the available Parameters in the active version.
If you're running 5.1 or older, the Get-Help -Name Set-Service -Parameter Credential should return the error "No parameter matches criteria.".
Installing or updating to PowerShell 7.X is as easy as running winget install Microsoft.PowerShell.
Why don't you want to use:
sc.exe config "[servicename]" obj= "[.\username]" password= "[password]"
If you want the user to enter a username/password each time, then you can use:
$cred = Get-Credential
$username = $cred.username
$password = $cred.GetNetworkCredential().password
&sc.exe config "[servicename]" obj= "$username" password= "$password"
if you need to check that the username and password are valid, then you can use:
$currentdomain = "LDAP://" + ([ADSI]"").distinguishedName
$domain = New-Object System.DirectoryServices.DirectoryEntry($currentdomain,$username,$password)
if ($domain.name -eq $null) {
write-host "Authentication failed - please verify your username and password."
exit
}
else {
write-host "Successfully authenticated with domain $domain.name"
}

Powershell Direct from Jenkins to Hyper-v Windows 10

I have been trying to use Jenkins to automatically test VMs, which includes copying new code into the VM, or running certain commands from the host into the VM using Powershell Scripts.
However, I've been running into an error trying to using "Invoke-Command" or "New-PSSession" to a hyper-V Windows 10 VM in Jenkins Freestyle and Pipeline projects.
This is the environment Jenkins is running on:
Windows Specifications:
Edition: Windows Server 2019 Standard
Version: 1809
OS build: 17763.379
Jenkins ver. 2.190.1
Hyper-V Manager: 10.0.17763.1
This is the Powershell Scripts that I've written in a "Windows Powershell" Build Step in a freestyle project:
# Win10-Clean is currently running and the credentials are for the Win 10 VM.
$ErrorActionPreference = "Stop"
$VMName = "Win10-Clean"
$username = "username"
$pwd = "password"
$secpasswd = ConvertTo-SecureString $pwd -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ("$username", $secpasswd)
Get-VM
Invoke-Command -Credential $mycreds -VMName $VMName -ScriptBlock {host}
I expect the output to be:
Running as SYSTEM
Building on master in workspace G:\ci_server_1\jenkins\workspace\powershell-testing-ground
[powershell-testing-ground] $ powershell.exe -NonInteractive -ExecutionPolicy ByPass "& 'C:\Windows\TEMP\jenkins6936256398230803297.ps1'"
Name State CPUUsage(%) MemoryAssigned(M) Uptime Status Version
---- ----- ----------- ----------------- ------ ------ -------
Win10-Clean Running 0 1854 5.14:10:42.5100000 Operating normally 8.3
PSComputerName : Win10-Clean
RunspaceId : 56151e46-5772-458f-8f11-9beba5491bc2
Name : ServerRemoteHost
Version : 1.0.0.0
InstanceId : fe09fc40-8434-4a7c-903b-b7b2c3f88506
UI : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture : en-US
CurrentUICulture : en-US
PrivateData :
DebuggerEnabled : True
IsRunspacePushed : False
Runspace : System.Management.Automation.Runspaces.LocalRunspace
Finished: SUCCESS
But what I got was this:
Running as SYSTEM
Building on master in workspace G:\ci_server_1\jenkins\workspace\powershell-testing-ground
[powershell-testing-ground] $ powershell.exe -NonInteractive -ExecutionPolicy ByPass "& 'C:\Windows\TEMP\jenkins233354859509300046.ps1'"
An error has occurred which Windows PowerShell cannot handle. A remote session might have ended.
At C:\Windows\TEMP\jenkins233354859509300046.ps1:7 char:1
+ Invoke-Command -Credential $mycreds -VMName Build_VM -ScriptBlock {ho ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (Build_VM:String) [], PSRemotingDataStructureException
+ FullyQualifiedErrorId : PSSessionStateBroken
Build step 'Windows PowerShell' marked build as failure
Finished: FAILURE
After referring to the official microsoft web page regrding this issue, the possible causes are:
VM exists but not running
Guest OS does not support PowerShell Direct
Powershell isn;t avaliable in the guest yet:
Operation system hasn't booted yet
OS can't boot correctly
Some boot time event needs user input
A bug in current builds where credentials must be explicitly passed with -Credential. Run Restart-Service -Name vmicvmsession as a work around.
However, from the output from Jenkins, the VM that I've been trying to connect to is "Running" and it is booted up properly.
Then, I've tried to "Invoke-Command" and "New-PSSession" into the VM from the host directly and I am able to connect to the VM.
I've also tried the same thing in a Jenkins installed in a Windows 10 machine instead of a windows server 2019 and everything works.
As for the user administrative information, the user logged in that is running Jenkins is both the "administrator" and the "hyper-v administrator".
These are some of the references I used to debug and I'm not able to find out what the problem is:
Remote Access With PowerShell and Jenkins, but I'm not able to figure out how exactly this works.
Running Powershell scripts using Jenkins
PowerShell: error executing command using Invoke-Command?
EDITS:
I found a way around this issue. Please mind that this isn't the definite solution but a work around.
Instead of running Invoke-Command -Credential $mycreds -VMName $VMName -ScriptBlock {host}, run this:
Invoke-Command -ComputerName "MyHostComputer" -ScriptBlock {Invoke-Command -Credential $mycreds -VMName $VMName -ScriptBlock {host}}
This command is essentially invoke-commanding into the host machine and use the host machine to run the Invoke-Command into the VM.
It is definitely not the perfect solution, but before anyone has a better solution I'll go with this for now.

Access denied while running Windows Update using Powershell's Invoke-Command

I've been trying to setup a Powershell module that would remotely call Windows/Microsoft update on a server using Invoke-Command, then process the updates, and send everything back to the calling server so it can send an email report.
My issue comes when I try and call the downloader: Powershell seems to be requesting Elevated rights on the remote computer.
Here is a snippet of what I'm trying to run and fail:
Invoke-Command -ComputerName $Server -Credential $Credentials -ScriptBlock {
$UpdateSession = New-Object -ComObject "Microsoft.Update.Session"
Write-Progress -Activity "Updating" -Status "Checking for new updates"
$Criteria = "IsInstalled=0 and Type='Software'"
$Updates = $UpdateSession.CreateUpdateSearcher().Search($Criteria).updates
$Downloader = $UpdateSession.CreateUpdateDownloader()
$Downloader.Updates = $Updates
}
I know the issue isn't with remoting, as the first 4 commands work fine.
The $Credentials variable points to pre-defined credentials, which are Local Admin on the remote server.
When the script gets to the 5th line, $Downloader = $UpdateSession.CreateUpdateDownloader(), I get this error from Powershell:
Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
+ CategoryInfo : OperationStopped: (:) [], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException
+ PSComputerName : SERVER.sidlee.inc
What could be causing this exactly ?
Thanks in advance for the help!
As i just hit the same wall, and Google isn't of much help either, here is what i could dig up.
For the record, i am pretty much doing the same thing (using custom PS code to check remote systems for Windows Updates) but using WinRM over Python instead of Invoke-Command and also got stuck on Microsoft.Update.Searcher.Search() throwing a E_ACCESSDENIED error.
The UnauthorizedAccessException is indeed not related to Powershell but the underlying API.
I suspect Microsoft started cutting off impersonation in remote session in some recent update (Powershell v5?) as this was (and still is) working just fine on older Windows versions (e.g. Server 2012 with Powershell v3 or 2012 R2 with v4)
To get around this you will need to authenticate (on the remote server) prior to executing your stuff with a PSCredential object.
So Remote Auth -> Local Auth -> Run stuff for example using Start-Process -Credential ...
e.g.
$pass = ConvertTo-SecureString "PA$$W0RD" -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential "User", $pass
Start-Process -Credential $creds powershell -ArgumentList "-Command & { ... whatever you want to do ... }"
Keep in mind that this poses a security risk as your password will be parsed in clear text, so don't do this over an
unencrypted channel!

Run remote Powershell session as version 2

I'm on a server that is running Powershell Version 2:
PS C:\> $PSVersionTable
Name Value
---- -----
...
PSVersion 2.0
I then create a new remote session to a different computer and connect to it:
$sess = New-PSSession -ComputerName {ComputerName} -Credential $credential
It returns me the result:
PS C:\> Invoke-Command -Session $sess -ScriptBlock { $PSVersionTable }
Name Value
---- -----
...
PSVersion 3.0
However, I need Powershell to be in Version 2 for my script so I enter a session (to make it easier). I then try to get Powershell to be Version 2:
C:\> Enter-PSSession -Session $sess
[{ComputerName}]: PS C:\> Powershell -Version 2
Windows Powershell
Copyright (C) 2009 Microsoft Corporation. All rights reserverd
And then it just hangs (or at least never lets me enter anything else into the console until I Ctrl-C).
I've also tried going through the Invoke-Command:
PS C:\> Invoke-Command -Session $sess -ScriptBlock { Powershell -version 2 }
and it does the same.
I've also tried to register a PSSessionConfiguration as per here: https://technet.microsoft.com/en-us/library/hh847899.aspx
PS C:\> Register-PSSessionConfiguration -Name PS2 -PSVersion 2.0
But I get:
Register-PSSessionConfiguration: a parameter cannot be found that matches parameter name 'PSVersion'.
Does anyone have any ideas of what I can try next?!
Thanks
On what machine did you run Register-PSSessionConfiguration?. Your computer or the "server"?
You need to make the configuration on the target server. That is what you will be running the hosted PSSessionConfiguration.
I just tried the steps in the technet article and it worked perfectly. My 2008 server remoted to my windows 7 machine running a 2.0 PSSessionConfiguration.
On target server/host:
Register-PSSessionConfiguration -Name PS2 -PSVersion 2.0
Then, on the client machine, reference the 'PS2' configuration.
$s = New-PSSession -ComputerName Server01 -ConfigurationName PS2
I take it that the following doesn't work either:
#Requires -version 2.0
Another kluge you could try is to create a scheduled task on the target and have the task fire off your script with Powershell.exe -version 2

How to invoke Powershell version 2 on remote computer via Invoke-Command

I'm trying to remotely setup websites on web servers using powershell. The web servers I'm attempting to configure are Windows Server 2008 R2 SP1 which has powershell v2 on it by default.
To make things easier, I'm using the Snapin "WebAdministration".
Whenever I attempt to invoke a the following command:
PS C:\p4\eacp4wireframe\ReleaseEngineering\DL_Powershell\Infrastructure\PowerShell\IIS> Invoke-Command -ComputerName web4 -Credential $admin -ScriptBlock {add-pssnapin WebAdministration; Get-Website}
No snap-ins have been registered for Windows PowerShell version 2.
+ CategoryInfo : InvalidArgument: (WebAdministration:String) [Add-PSSnapin], PSArgumentException
+ FullyQualifiedErrorId : AddPSSnapInRead,Microsoft.PowerShell.Commands.AddPSSnapinCommand
I get the dreaded "No snap-ins have been registered for Windows PowerShell version 2" error.
Logically, I check the version of powershell by running this command:
PS C:\ Invoke-Command -ComputerName web4 -Credential $admin -ScriptBlock {(Get-Host).version}
Major Minor Build Revision PSComputerName
----- ----- ----- -------- --------------
1 0 0 0 web4
I can remotely login to the web server and run the Powershell commands fine.
Any ideas?
That version number is the version number of the host implementation used by remoting e.g.:
C:\PS> Invoke-Command . {Get-Host | Get-Member}
TypeName: System.Management.Automation.Internal.Host.InternalHost
You have to be using at least the PowerShell 2.0 engine because that is when PowerShell Remoting was introduced. It is more likely that you're invoking the 64-bit PowerShell remoting endpoint and you have snapins that either haven't been registered for the 64-bit PowerShell or won't run in 64-bit PowerShell (or vice versa).
If you need to invoke the 32-bit remoting endpoint try this:
C:\PS> Invoke-Command . {[intptr]::size} -ConfigurationName Microsoft.PowerShell32
4