How Azure Function using PowerShell can issue Invoke-Command to another computer? - powershell

I am trying to do something straightforward, use PowerShell Invoke-Command from an Azure Function. The destination machine is in my Azure subscription and in the same virtual network. The code below fails with the error below.
A difficulty is that Azure Functions are "serverless" so when I try various solutions, such as setting the local TrustedHosts file, it fails because there is no such file.
I want to use the simplest method that is reasonably secure. I tried various other authentication schemes with no luck.
using namespace System.Net
# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)
$adminName = 'chuck-admin'
$adminPassword = 'XXXXXXX'
$secPassword = ConvertTo-SecureString $adminPassword -AsPlainText -Force
$vmCreds = New-Object System.Management.Automation.PSCredential ($adminName, $secPassword)
$vmReturn = Invoke-Command -ComputerName chuck-vm-3 -Credential $vmCreds -ScriptBlock{whoami}
Push-OutputBinding -Name Response -Value ([HttpResponseContext]#{
StatusCode = [HttpStatusCode]::OK
Body = $vmReturn
})
System.Management.Automation.Remoting.PSRemotingTransportException:
Connecting to remote server chuck-vm-3 failed with the following error message :
The WinRM client cannot process the request. If the authentication scheme is different from Kerberos, or if the client computer is not joined to a domain, then HTTPS transport must be used or the destination machine must be added to the TrustedHosts configuration setting.
Use winrm.cmd to configure TrustedHosts. Note that computers in the TrustedHosts list might not be authenticated.
You can get more information about that by running the following command: winrm help config. For more information, see the about_Remote_Troubleshooting Help topic.

Related

Permissions required to use Move-VM remotely in Hyper-v 2016

I am attempting to run the PowerShell command "move-vm" remotely but I am getting permissions errors that I can't seem to get past.
My move-vm command looks like this:
move-vm -ComputerName SorceHost -Name $vm.name -DestinationHost $DestHost -IncludeStorage -DestinationStoragePath d:\vms -DestinationCredential $cred -Credential $cred
and I am defining the credentials like this
$username = ".\PSAPIUser"
$password = Get-Content 'C:\key\PSAPIAUTH.txt' | ConvertTo-SecureString
$cred = new-object -typename System.Management.Automation.PSCredential `
-argumentlist $username, $password
Both the source and destination are on the same AD domain, and I have created a domain admin account specifically for this function. I have added the domain admins group to the local groups 'Hyper-V administrators' 'administrators' on the source and destination hosts. When I issue the command I get:
move-vm : You do not have the required permission to complete this task. Contact the administrator of the authorization policy for the computer 'SourceHost'.
There are various articles out there about how to do this in 2012, however, its my understanding that the process has changed significantly in 2016 due to the depreciation of something called authorisation manager.
Does anyone have any experience on how to configure permissions to allow remote Hyper-V management with PowerShell specifically in 2016?
Thanks in advance.
Edit:
$cred = Get-Credential
$cred
UserName Password
-------- --------
PSAPIuser#domain.net System.Security.SecureString
move-vm : You do not have the required permission to complete this task. Contact the administrator of the authorization policy for the computer
Managing Hyper-V remotely uses something called Constrained Delegation. Imagine the scenario.
You are on the host Man1, and you are issuing a command to Hyp-001 to move a VM to Hyp-002. So you have Man1 issuing commands to Hyp-001, which is fine as it can use your credentials, but when Hyp-001 passes commands to Hyp-002 it has no credentials to pass, hence you get the error
move-vm : Virtual machine migration operation failed at migration source.
Failed to establish a connection with host 'ng2-vps-011.hyperslice.net': No credentials are available in the security package
to get around this you need to give specific permissions that allows hosts to run specific services on each other, within AD delegation.
From PowerShell it would look like this:
Set-ADObject -Identity $HostDeetsArra.Disname -ADD #{"msDS-AllowedToDelegateTo"="$service1/$Disname","$Service1/$HostName"}
#$disnam = distignushed name, $Service1 is the service 'cifs' $hostanme is the FQDN
In 2016 you also need this:
Set-ADAccountControl -Identity $HostDeetsArra.Disname -TrustedToAuthForDelegation $true
My source for this information is below
https://www.altaro.com/hyper-v/free-powershell-script-configure-constrained-delegation-hyper-v/

Remote Execution of a PowerShell script results in "The WinRM client cannot process the request. [...] HTTPS transport must be used [...]"

I have written a PowerShell script which uninstall a program and install a newer version of the program on my servers (Update Programs). Now I want to create another script which run the aforementioned script on the servers. Consider that I have to connect to my servers through using IPs, UserName and password and using domain is not an option.
How is this possible?
PowerShell version is 4
I have tried this code to simply get date:
$User = "administrator"
$PWord = ConvertTo-SecureString -String "Password1234" -AsPlainText -Force
$Credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $User, $PWord
$session = New-PSSession -ComputerName '10.60.60.100' -Credential $Credential
Invoke-Command -Session $session -ScriptBlock {Get-Date}
and I got this error:
New-PSSession : [10.60.60.100] Connecting to remote server 10.60.60.100 failed with the following error message : The WinRM client cannot process the request. If the authentication scheme is different from Kerberos, or if the client computer is not joined to a domain, then HTTPS transport must be used or the destination machine must be added to the TrustedHosts configuration setting. Use winrm.cmd to configure TrustedHosts. Note that computers in the TrustedHosts list might not be authenticated. You can get more information about that by running the following command: winrm help config. For more information, see the about_Remote_Troubleshooting Help topic.
This is because you’re not running your command from a trusted host, or because the remote computers wsman service isn’t configured properly. I’d start by running the following command to configure wsman on the remote machine:
wsman quickconfig
If that doesn’t fix the problem, then you need to add your computer to the remote machines trusted hosts. You can do that by running the following:
winrm s winrm/config/client '#{TrustedHosts="RemoteComputer"}'

Remote Powershell scripting and Jenkins not working

I am having an issue running a remote script using Jenkins. I have installed the PowerShell plug-in and can run PowerShell scripts on the local build server, but when I try to run it on a remote server, it fails all the time. I can run the same script outside of Jenkins locally and remotely and it works just fine. My assumption is that there is a security setting I am missing but for the life of me, I can not find it.
Any insight/help would be greatly appreciate it.
The code below runs using PowerShell on the server but not through Jenkins:
$ErrorActionPreference = 'Stop'
# Create a PSCredential Object using the "User" and "Password" parameters
that you passed to the job
$SecurePassword = 'xxxxxxx' | ConvertTo-SecureString -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList 'ci-user', $SecurePassword
# Invoke a command on the remote machine.
# It depends on the type of job you are executing on the remote machine as
to if you want to use "-ErrorAction Stop" on your Invoke-Command.
Invoke-Command -ComputerName xxx.xx.xx.xxx -Credential $cred -ScriptBlock {
# Restart the W32Time service
Restart-Service -Name W32Time
}
The error below is what I get when I run it in Jenkins. I am using the same username and password when I run it outside of Jenkins and works:
Connecting to remote server xxx.xx.xx.xxx failed with the
following error message : WinRM cannot process the request. The following
error with errorcode 0x8009030d occurred while using Negotiate authentication:
A specified logon session does not exist. It may already have been terminated.
Possible causes are:
-The user name or password specified are invalid.
-Kerberos is used when no authentication method and no user name are
specified.
-Kerberos accepts domain user names, but not local user names.
-The Service Principal Name (SPN) for the remote computer name and port does
not exist.
-The client and remote computers are in different domains and there is no
trust between the two domains.
After checking for the above issues, try the following:
-Check the Event Viewer for events related to authentication.
-Change the authentication method; add the destination computer to the WinRM
TrustedHosts configuration setting or use HTTPS transport.
Note that computers in the TrustedHosts list might not be authenticated.
-For more information about WinRM configuration, run the following command:
winrm help config. For more information, see the about_Remote_Troubleshooting
Help topic.
At C:\Windows\TEMP\jenkins3589460126620702793.ps1:12 char:1
+ Invoke-Command -ComputerName xxx.xx.xx.xxx -Credential $cred -ScriptBlock {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (xxx.xx.xx.xxx:String) [], PSRemoting
TransportException
+ FullyQualifiedErrorId : 1312,PSSessionStateBroken
This could be caused by a few different issues:
Are your remote machine and connecting machine on the same domain? If not, verify the domain of your ci-user and retry.
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList
'connectingserver/ci-user', $SecurePassword
Is WinRM enabled on your remote server, is the WinRM service running, are you setup to allow the appropriate remoting? Follow these steps to verify: https://technet.microsoft.com/en-us/library/ff700227.aspx?f=255&MSPPError=-2147217396
Are both the remote and connecting server setup with the same authentication method? You will want to use either Kerberos or CredSSP. I would consider CredSSP only if you are trying to solve the Double-Hop issue.
I found the error of my ways but hopefully this answer will help anyone else that encounters it.
The problem was that the user I am using is a local user and it needs to be treated as a workgroup user. So instead of ci-user, I needed to pass it as \ci-user. Once I did this, it works like a charm.
Thank you for all your input.

Powershell New-PSSession issue

When I remote desktop to a box I will get a prompt like this:
Once I select "Yes" I am connected to the box. When I try to login to the same box with the same credentials in PowerShell I get the error listed at the end of this post.
$secPasswd = ConvertTo-SecureString $password -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential($username, $secPasswd)
$session = New-PSSession –ComputerName $hst -Credential $creds
where $hst is "MyBox" and $username is "MyBox\MyUser"
Q: Is there a way in powershell for me to mimic the selection of the "Yes" button?
ERROR:
New-PSSession : [MyBox] Connecting to remote server MyBox failed with the following error message : WinRM cannot process the request. The following error with errorcode 0x80090311 occurred while using Kerberos authentication: There are
currently no logon servers available to service the logon request.
Possible causes are:
The user name or password specified are invalid.
Kerberos is used when no authentication method and no user name are specified.
Kerberos accepts domain user names, but not local user names.
The Service Principal Name (SPN) for the remote computer name and port does not exist.
The client and remote computers are in different domains and there is no trust between the two domains.
After checking for the above issues, try the following:
Check the Event Viewer for events related to authentication.
Change the authentication method; add the destination computer to the WinRM TrustedHosts configuration setting or use HTTPS transport.
Note that computers in the TrustedHosts list might not be authenticated.
For more information about WinRM configuration, run the following command: winrm help config. For more information, see the about_Remote_Troubleshooting Help topic.
Analysis on target box
WinRM is running
Expected firewall rules are in place
User is part of the admin group
PSRemoting is enabled

powershell v2 remoting - How do you enable unencrypted traffic

I'm writing a powershell v2 script that I'd like to run against a remote server. When I run it, I get the error :
Connecting to remote server failed
with the following error message : The
WinRM client cannot process the
request. Unencrypted traffic is
currently disabled in the client
configuration. Change the client
configurati on and try the request
again. For more information, see the
about_ Remote_Troubleshooting Help
topic.
I looked at the online help for about _ Remote_Troubleshooting, but it didn't point me towards how to enable unecrypted traffic. Below is the script that I'm using that is causing me problems.
Note: I have already run Enable-PSRemoting on the remote machine to allow it to accept incoming requests.
I have tried to use a session option variable, but it doesn't seem to make any difference.
$key = "HKLM:\SOFTWARE\Microsoft\PowerShell\1\ShellIds"
Set-ItemProperty $key ConsolePrompting True
$tvar = "password"
$password = ConvertTo-SecureString -string $tvar -asPlainText –force
$username="domain\username"
$mySessionOption = New-PSSessionOption -NoEncryption
$credential = New-Object System.Management.Automation.PSCredential($username,$password)
invoke-command -filepath C:\scripts\RemoteScript.ps1 -sessionoption $mySessionOption -authentication digest -credential $credential -computername RemoteServer
How do I enable unencrypted traffic?
AllowEncrypted is defined on the client end, via the WSMAN: drive. You must be running powershell.exe (or powershell_ise.exe) as an elevated process.
ps> cd WSMan:\localhost\Client
ps> dir
Name Value
---- -----
NetworkDelayms 5000
URLPrefix wsman
AllowUnencrypted false
Auth
DefaultPorts
TrustedHosts
You would change it like so (after changing to the directory above):
Set-Item .\allowunencrypted $true
Hope this helps,
Oisin
You probably will need to set the AllowUnencrypted config setting in both the Client and the Service. The Service setting has to be changed in the remote server using the following:
set-item -force WSMan:\localhost\Service\AllowUnencrypted $true
And don't forget to also enable Digest Authorization:
set-item -force WSMan:\localhost\Service\Auth\Digest $true
You can allow unencrypted traffic on the client with the following command (execute it on the client):
winrm set winrm/config/client '#{AllowUnencrypted="true"}'
To verify, you can get the whole config (client and service) with this command:
winrm get winrm/config
Be aware that each machine has two configs (one for being a client, one for beeing a server). To allow unencrypted traffic on the server, execute the following command on the server:
winrm set winrm/config/service '#{AllowUnencrypted="true"}'
This worked for me:
enable-wsmancredssp –role server
If the parameter AllowUnencryptedTraffic is under GPO, you can set it through registrar:
$RegPath = 'HKLM:\Software\Policies\Microsoft\Windows\WinRM\Client'
$RegUnencryptedTraffic = 'AllowUnencryptedTraffic'
$RegValue = '1'
Set-ItemProperty -Path $RegPath -Name $RegUnencryptedTraffic -Value $RegValue