Overcoming Double Hop Issues with PowerShell Remoting

While working in an environment that does not have Kerberos delegation configured I hit the classic double hop authentication problem. This time it reared its ugly head while trying to use the Windows PowerShell Extensions for Microsoft SQL Server 2012 (not to be confused with the community driven SQL Server PowerShell Extensions). When executing Backup-SqlDatabase on a management console via PowerShell Remoting as part of a build process managed by TeamCity I hit the following error:

Backup-SqlDatabase : Failed to connect to server FOOBAR

To troubleshoot I ran the cmdlet on the management console via RDP and it worked great. Next I tried to run it the management console through a PowerShell remoting session and that is when I received the same error as my build process. Using the -Debug parameter I was able to see that under the covers that the command constructs a connection string that is used to create a SQL connection using the same Windows authentication method that you would see in an application like SQL Management Studio. Stepping back from the problem it became clear that I was double hopping:

I needed a way to get around this without waiting in line for the system and database administrators to configure Kerberos correctly. After a bit of searching the answer appeared - CredSSP. Luckily the Windows Management Framework team is all over this by implementing CredSSP through the WS-Management service. Designed to solve problems associated with Terminal Services where everything could be a double hop it allows you to delegate the token to specific computers. Before you rush into it there are two configuration steps - enable the server, configure the trusted computers on the client.

Enabling Remote Server to use Delegated Credentials

Setting up the server to accept delegated credentials is straight forward. From an elevated PowerShell session use the following command:

Enable-WSManCredSSP -Role Server

That is all you need to do on that end.

Configuring Clients to Delegate Credentials to Trusted Hosts

The client side configuration is a bit more involved in that you need to specify which computers are trusted for delegation. From an elevated PowerShell session use the following command:

Enable-WSManCredSSP -Role Client -DelegateComputer foobar.domain.com

You can also use a wildcard to specify a range of computers, for example *.domain.com for all computers in domain.com or * for all computers.

Making the First Hop with CredSSP

Once you are configured on both sides for CredSSP it is time to initiate the PowerShell remote session:

$Username = "DOMAIN\BuildAgent"    
$SecurePassword = ConvertTo-SecureString -AsPlainText -Force -String P@ssw0rd
$RemoteCredential = New-Object System.Management.Automation.PSCredential($Username,$SecurePassword)
$RemoteSession = New-PSSession MANAGEMENTCONSOLE -Credential $RemoteCredential -Authentication CredSSP
Invoke-Command -ScriptBlock { ... } -Session $RemoteSession

Before you get all concerned about the clear text password there are, of course, better ways to manage secure string which I would recommend. There is also a suggestion open on the PowerShell feedback site to ask the product group to make it possible to use the current user credentials rather than managing an encrypted password- I would encourage you to upvote it. Once connected you are able to run all of the necessary commands as if you were directly connected on the machine.