dennisgorelik: (2009)
Dennis Gorelik ([personal profile] dennisgorelik) wrote2016-08-10 11:11 pm

Remote PowerShell

We tried to run PowerShell remotely (in order to automate build deployment).
We managed to make it work on developers' machines, but on production server it just refuses to work:
----------------------------------------------------------------
C:\Windows\system32>powershell
Windows PowerShell

PS C:\Windows\system32> Enable-PSRemoting -SkipNetworkProfileCheck -Force
WinRM is already set up to receive requests on this computer.
Set-WSManQuickConfig : <f:WSManFault
xmlns:f="http://schemas.microsoft.com/wbem/wsman/1/wsmanfault" Code="2"
Machine="localhost"><f:Message><f:ProviderFault provider="Config provider"
path="%systemroot%\system32\WsmSvc.dll"><f:WSManFault
xmlns:f="http://schemas.microsoft.com/wbem/wsman/1/wsmanfault" Code="2"
Machine="sv7731"><f:Message>Unable to check the status of the firewall.
</f:Message></f:WSManFault></f:ProviderFault></f:Message></f:WSManFault>
At line:65 char:17
+                 Set-WSManQuickConfig -force -SkipNetworkProfileCheck
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   + CategoryInfo          : InvalidOperation: (:) [Set-WSManQuickConfig], InvalidOperationException
   + FullyQualifiedErrorId : WsManError,Microsoft.WSMan.Management.SetWSManQuickConfigCommand


PS C:\Windows\system32> Enter-PSSession -ComputerName localhost
Enter-PSSession : Connecting to remote server localhost failed with the
following error message : Access is denied. For more information, see the
about_Remote_Troubleshooting Help topic.
At line:1 char:1
+ Enter-PSSession -ComputerName localhost
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   + CategoryInfo          : InvalidArgument: (localhost:String) [Enter-PSSes
  sion], PSRemotingTransportException
   + FullyQualifiedErrorId : CreateRemoteRunspaceFailed

----------------------------------------------------------------

Note "Unable to check the status of the firewall." part of the message.
Why would Enable-PSRemoting command try to check the status of the firewall?

Another Windows WTF reported by yatur


Update
Finally we were able to fix this remote powershell issue.
The problem was in Group Policy for IpV4Filter on our production machine.
IpV4Filter was limited to a single IP address (main address of that production machine).
I have no idea why it was setup that way.

This is how I fixed WinRM localhost access problem:
Run gpedit.msc
Local Computer Policy
Computer Configuration
Administrative Templates
Windows Components
Windows Remote Management (WinRM)
WinRM Service
Allow remote server management through WinRM

In "IPv4 filter:" change "208.43.198.72" to "*":
IPv4 filter: *

FixIpV4FilterInGroupPolicy.jpg

In the end, PowerShell and Microsoft server tools leave a negative impression due to bugs and pathetic diagnostic.

Consider another PowerShell surprise:
"ls" and "dir" commands produce empty output in case when folder is empty. No headers, no message that says there are no files. Just nothing. WTF?

[identity profile] sab123.livejournal.com 2016-08-11 06:32 pm (UTC)(link)
Is the machine domain-joined? If not, try to enable the settings for the HTTP protocol on the client side:

Set-Item -Force WSMan:\localhost\Client\AllowUnencrypted true
Set-Item -Force WSMan:\localhost\Client\TrustedHosts *

In the firewall on the server, check the ports 5985 (WinRm HTTP) and maybe also 5986 (WinRM HTTPS).
Edited 2016-08-11 18:32 (UTC)

[identity profile] sab123.livejournal.com 2016-08-11 08:08 pm (UTC)(link)
2) No idea. The other command that can be used is "winrm quickconfig", and I think it creates the firewall rule among other things. BTW, Server 2016 should be pre-configured out of the box.

3) If it's not domain-joined, you have to use the option -Credential. Just give it the user name (like "~\administrator") and it will prompt you in the GUI for the password. Or generate the credential object from the name and password:

function mkcr
{
<#
.SYNOPSIS
Make a credentials object out of the user name and password.
#>
    param(
        ## User name.
        [string] $user,
        ## Password in plain text.
        [string] $passwd
    )
    $secpwd = ConvertTo-SecureString -Force -AsPlainText $passwd
    New-Object System.Management.Automation.PSCredential @($user, $secpwd)
}


then use -Credential (mkcr ".\administrator" "password")
For some weird reason the GUI form doesn't allow the syntax with "." for the host part in the username but does allow "~". If you don't use the host part on a non-domain-joined server, your connection will be very slow.

Setting up an HTTPS connection is a whole separate world of pain :-)

[identity profile] sab123.livejournal.com 2016-08-11 09:22 pm (UTC)(link)
I've tried, and yes, the localhost connection works without a password even without a domain. No idea what is the problem. Have you tried reading about_Remote_Troubleshooting? :-)

[identity profile] sab123.livejournal.com 2016-08-11 10:28 pm (UTC)(link)
It's the common Windows problem: the diagnostics tends to be limited to returning an error code that says "you've done something wrong", and even a lot of the error codes are unpublished externally.

Just in case, did you reboot the machine? If not, you can try restarting the WinRM service, i.e. "restart-service WinRM". Or rebooting.

Have you tried running "winrm quickconfig"? If not, try it. You can also test the connection by "winrm identify" (run it with /? to see the help).
Edited 2016-08-11 22:33 (UTC)

[identity profile] sab123.livejournal.com 2016-08-11 10:59 pm (UTC)(link)
1) Don't know, maybe. I think a reboot was required on the older versions. You can try connecting telnet to the port 5985, to see if the winrm server is running at all and the firewall is open.

BTW, try this:

PS C:\> dir WSMan:\localhost\Listener\
Type            Keys                                Name
----            ----                                ----
Container       {Transport=HTTP, Address=*}         Listener_1084132640


Does your result look anything like this?

Look in WSMan:\localhost\Service\ , does it look reasonable? In particular, what does WSMan:\localhost\Service\Auth\ contain for the authentication "negotiate"? What about WSMan:\localhost\Client?

Here is an example of what works for me:

PS C:\> dir WSMan:\localhost\Client
Type            Name                           SourceOfValue   Value
----            ----                           -------------   -----
System.String   NetworkDelayms                                 5000
System.String   URLPrefix                                      wsman
System.String   AllowUnencrypted                               true
Container       Auth
Container       DefaultPorts
System.String   TrustedHosts                                   *


PS C:\> dir WSMan:\localhost\Client\Auth\
Type            Name                           SourceOfValue   Value
----            ----                           -------------   -----
System.String   Basic                                          true
System.String   Digest                                         true
System.String   Kerberos                                       true
System.String   Negotiate                                      true
System.String   Certificate                                    true
System.String   CredSSP                                        true

PS C:\> dir WSMan:\localhost\Service\Auth\
Type            Name                           SourceOfValue   Value
----            ----                           -------------   -----
System.String   Basic                                          false
System.String   Kerberos                                       true
System.String   Negotiate                                      true
System.String   Certificate                                    false
System.String   CredSSP                                        true
System.String   CbtHardeningLevel                              Relaxed


PS C:\> dir WSMan:\localhost\Service\
Type            Name                           SourceOfValue   Value
----            ----                           -------------   -----
System.String   RootSDDL                                       O:NSG:BAD:P(A;;GA;;;BA)(A;;GR;;;IU)S:P(AU;FA;GA;;;WD)...
System.String   MaxConcurrentOperations                        4294967295
System.String   MaxConcurrentOperationsPerUser                 1500
System.String   EnumerationTimeoutms                           240000
System.String   MaxConnections                                 300
System.String   MaxPacketRetrievalTimeSeconds                  120
System.String   AllowUnencrypted                               false
Container       Auth
Container       DefaultPorts
System.String   IPv4Filter                                     *
System.String   IPv6Filter                                     *
System.String   EnableCompatibilityHttpList...                 false
System.String   EnableCompatibilityHttpsLis...                 false
System.String   CertificateThumbprint
System.String   AllowRemoteAccess                              true


(this machine also has CredSSP enabled, you don't really need that for the basic connections).

2) Looks like just nobody cares, it's not considered an important property and requires extra effort. The developers tend to create the one-off solutions for the problems that reach them, and these get occasionally published, so you can find a whole lot of the workaround recipes on the internet. Everything is built as workarounds on top of workarounds. So try going through the support channel, maybe you'll get a solution.

[identity profile] sab123.livejournal.com 2016-08-11 11:42 pm (UTC)(link)
Try Set-Item, like in the example above. I've actually never seen the filter set like this. "GPO" probably means the Group Policies, so you might have some weird settings there.

[identity profile] sab123.livejournal.com 2016-08-12 12:49 am (UTC)(link)
Looks like the group policies are stored in the registry under HKEY_LOCAL_MACHINE, so you can just search there for this particular address (and maybe change it right there too). Since the machine is not domain-joined, it shouldn't be downloading these policies from the domain.

Re: Finally fixed - IpV4Filter Global Policy configuration

[identity profile] sab123.livejournal.com 2016-08-12 06:09 pm (UTC)(link)
By the way, completely accidentally, today I've stumbled on a post on how to enable the logging on WSman:

https://blogs.msdn.microsoft.com/wmi/2010/03/16/collecting-winrm-traces/

Re: Finally fixed - IpV4Filter Global Policy configuration

[identity profile] sab123.livejournal.com 2016-08-12 11:38 pm (UTC)(link)
Never looked at them. :-)

"Operational" should be like the normal syslog level. "Analytical" and "Debug" get enabled by increasing the level of collected events, I didn't look too deeply into that yet. I guess the script had enabled only up to the analytical level.

If I remember right, the level numbering goes approximately like this:

0-5 - operational ("Error" to "Verbose")
up to 16 - analytical
up to 255 - debug

Re: Finally fixed - IpV4Filter Global Policy configuration

[identity profile] sab123.livejournal.com 2016-08-13 01:33 am (UTC)(link)
All the time.

Re: winrm identify

[identity profile] sab123.livejournal.com 2016-08-11 11:23 pm (UTC)(link)
Looks like the server is working and can be connected to. Try also "winrm identify -r:localhost"