Thursday, March 15, 2012

Setting up PS Remoting for all that PS/SP fun on your local box

With the boss out today and no major tasks beating down my door, I decided to take another swing at getting a sane and working PowerShell environment set up on my work PC. I was tired of having to remote into a server to do simple CLI stuff like getting internal field names and web GUIDs and the like.

The first time I was doing this, I was messing around with PowerGUI and trying to see about simple list iterations on the server, but I rapidly ran out of remote sessions and didn't know offhand how to easily reconnect to them. So, after five times, I had to start figuring out how to kill the remaining sessions before I could continue trying to figure out how to do actual things. Wasn't getting to be very fun.

Now for Take Two.

This time, I learned right away that I could easily manage the sessions by storing them in a variable and using Invoke-Command to do single-line command entry, like so:
PS > $session = New-PSSession -ComputerName TargetHost
PS > Invoke-Command -Session $session -ScriptBlock { Get-ChildItem C:\ } 
Simple enough so far. But obviously cumbersome. I'd already played around with Enter-PSSession before though, so was it easy enough to simply write Enter-PSSession $session?
PS > Enter-PSSession $session
[TargetHost]: PS > Get-ChildItem C:\
Apparently so! Exit-PSSession will return you to your local host, with $session intact, and you can run Remove-PSSession $session once you're finished to clean up after yourself.


Now then, I can at last experiment without worrying about locking myself out.


So, for the new user, it doesn't take long to figure out that while you're on a SharePoint server, the regular PowerShell just won't do. You must either launch the SP-provided PowerShell launcher, or run the basic PowerShell client and then run Add-PSSnapIn Microsoft.SharePoint.PowerShell to get access to the SharePoint-specific cmdlets. So, what happens when I run this in my session?
Cannot access the local farm. Verify that the local farm is properly configured, currently available, and that you have the appropriate permissions to access the database before trying again.
Now, I have this permssion on my own account when I run the PowerShell client via RDP on the server, so what gives? Enter this excellent article from JoshGav which explains that the culprit is our old nemesis, the double-hop authentication problem! Curses!

Following the instructions within mostly worked, but running Enable-WSManCredSSP -Role Client -DelegateComputer * -Force would always fail with the following:
Enable-WSManCredSSP : The client cannot connect to the destination specified in the request. Verify that the service on the destination is running and is accepting requests. Consult the logs and documentation for the WS-Management service running on the destination, most commonly IIS or WinRM. If the destination is the WinRM service, run the following command on the destination to analyze and configure the WinRM service: "winrm quickconfig".
At line:1 char:20
+ Enable-WSManCredSSP <<<<  -Role Client -DelegateComputer CSLISP2010WFE -Force
    + CategoryInfo          : InvalidOperation: (System.String[]:String[]) [Enable-WSManCredSSP], InvalidOperationException
    + FullyQualifiedErrorId : WsManError,Microsoft.WSMan.Management.EnableWSManCredSSPCommand
A couple of MSDN forum postings later, and I got to the point where I confirmed that the problem was that I had enabled remoting on the server...but silly me, I still needed to enable it on the client!
PS C:\Users\Me> Enable-PSRemoting

WinRM Quick Configuration
Running command "Set-WSManQuickConfig" to enable this machine for remote management through WinRM service.
 This includes:
    1. Starting or restarting (if already started) the WinRM service
    2. Setting the WinRM service type to auto start
    3. Creating a listener to accept requests on any IP address
    4. Enabling firewall exception for WS-Management traffic (for http only).

Do you want to continue?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): y
WinRM has been updated to receive requests.
WinRM service type changed successfully.
WinRM service started.

Set-WSManQuickConfig : WinRM firewall exception will not work since one of the network connection types on this machine is set to Public. Change the network connection type to either Domain or Private and try again.
At line:50 char:33
+             Set-WSManQuickConfig <<<<  -force
    + CategoryInfo          : InvalidOperation: (:) [Set-WSManQuickConfig], InvalidOperationException
    + FullyQualifiedErrorId : WsManError,Microsoft.WSMan.Management.SetWSManQuickConfigCommand
Aha. I had read on this earlier in my research, and I already knew the culprit - VirtualBox. Luckily, I located this helpful article by Thijs Kroesbergen which details how to exclude VirtualBox from network management so that I can enable CredSSP.

So, now we're golden right? Wrong. Now, when I try to run Enable-PSRemoting, I get sent back a simple "Access is denied." error. Well, that's just peachy. One last bit of research tells me that I must be *explicitly* placed in my machine's local Administrators group.
Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.

PS C:\Users\Me> Enable-PSRemoting

WinRM Quick Configuration
Running command "Set-WSManQuickConfig" to enable this machine for remote management through WinRM service.
 This includes:
    1. Starting or restarting (if already started) the WinRM service
    2. Setting the WinRM service type to auto start
    3. Creating a listener to accept requests on any IP address
    4. Enabling firewall exception for WS-Management traffic (for http only).

Do you want to continue?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): a
WinRM already is set up to receive requests on this machine.
WinRM already is set up for remote management on this machine.
PS C:\Users\Me> Enable-WSManCredSSP -Role Client -DelegateComputer * -Force


cfg         : http://schemas.microsoft.com/wbem/wsman/1/config/client/auth
lang        : en-US
Basic       : true
Digest      : true
Kerberos    : true
Negotiate   : true
Certificate : true
CredSSP     : true



PS C:\Users\Me> $session = New-PSSession SPSERVER -Authentication CredSSP -Credential DOMAIN\Me
PS C:\Users\Me> Enter-PSSession $session
[spserver]: PS C:\Users\Me\Documents> Add-PSSnapIn Microsoft.SharePoint.PowerShell
[spserver]: PS C:\Users\Me\Documents> $site = Get-SPSite("https://my.site.com/")
[spserver]: PS C:\Users\Me\Documents> $site

Url
---
https://my.site.com
Success!

3 comments:

  1. Thank-you very much for this awesome post - really helped me out a ton! That part about Enable-PSRemoting on the client (too) was very helpful!

    ReplyDelete
  2. I wish I understood why remote powershell is a hop for authentication, but RDP is not a hop. Why is RDP not a hop?

    ReplyDelete
  3. I believe RDP is not a hop because the host process for a remote desktop is running within your own user context when you log in via RDP.

    In PowerShell, the PS engine (not the interface) runs within the Windows Management Framework service. Therefore (assuming I'm correct as to the source of the problem), your local instance of the WM framework (running as Local Service or whathaveyou) is talking to the remote instance of the WM framework (within whatever context that service is running as on that system).

    ReplyDelete