Summary: Richard Siddaway explains how to configure remoting.
Hey, Scripting Guy! I’ve just starting learning WindowsPowerShell, and I understand how to use it as a scripting language and shell on the local machine. How do I work with remote machines?
—AP
Hello AP,
Honorary Scripting Guy, Richard Siddaway, here today filling in for my good friend, The Scripting Guy. This is the third part in a series of five posts about remoting. The series includes:
- Remoting Recap
- Remoting Sessions
- Configuring Remoting
- Remoting security
- Non-domain remoting
In the first post, you saw how Windows PowerShell supplies a number of options for individual cmdlets to access remote machines. This was followed in the second post by a look at using Windows PowerShell sessions to give you a reusable connection to the remote machine for efficiency.
In this third post, you will learn about three things:
- Overcoming the second hop issue
- Using HTTPS instead of HTTP for your WSMAN connection
- Configuring endpoints
Overcoming second hop
First off, what’s the second hop issue?
Imagine this scenario…
You’re working on your local machine (Win81) and you need to perform some tasks on two remote machines (Win12R2 and W08R2SQL08).
You can create sessions to both remote machines:
$sessw12 = New-PSSession -ComputerName Win12R2
$sessw08 = New-PSSession -ComputerName W08R2SQL08
And you can run commands against both machines:
Invoke-Command -Session $sessw12 -ScriptBlock {Get-Service}
Invoke-Command -Session $sessw08 -ScriptBlock {Get-Service}
Invoke-Command -Session $sessw12, $sessw08 -ScriptBlock {Get-Service}
Now, if you try to access W08R2SQL08 through a remote session from Win12R2, what will happen?
Invoke-Command -Session $sessw12 -ScriptBlock {Get-Service -ComputerName w08r2sql08}
Cannot open Service Control Manager on computer 'w08r2sql08'. This operation might require other privileges.
+ CategoryInfo : NotSpecified: (:) [Get-Service], InvalidOperationException
+ FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.PowerShell.Commands.GetServiceCommand
+ PSComputerName : Win12R2
So you perform a quick test:
Get-Service -ComputerName w08r2sql08
And you discover that it works!
You have just tripped over the second hop issue. You aren’t allowed to remote into one machine and run commands from that machine against other machines. It is essentially a permissions issue in that your credentials haven’t been delegated to the second machine, so it doesn’t have the rights to perform those actions.
There is one caveat to this that I’ve discovered. If the machine you are remoting to is a domain controller, you will be able to run some, but not all, commands against another machine. I haven’t fully explored this, but because it’s not a best practice to use your domain controllers in this manner, I’ll say no more.
How do we overcome this?
The answer is that you have to delegate your permissions to the second machine. This is achieved by using CredSSP. You get three cmdlets for working with CredSSP:
Disable-WSManCredSSP
Enable-WSManCredSSP
Get-WSManCredSSP
Enabling CredSSP has to be performed on the local and the remote machine. On the local machine, you enable the client role:
£> Enable-WSManCredSSP -Role Client -DelegateComputer win12r2.manticore.org -Force
cfg : http://schemas.microsoft.com/wbem/wsman/1/config/client/auth
lang : en-GB
Basic : true
Digest : true
Kerberos : true
Negotiate : true
Certificate : true
CredSSP : true
The Force parameter stops you from being prompted for confirmation. You could use wildcard characters for delegated computers, which could be *.manticore.org for all machines in the domain—or even * for all machines. You can verify the settings:
£> Get-WSManCredSSP
The machine is configured to allow delegating fresh credentials to the following target(s): wsman/Win12R2.manticore.org
This computer is not configured to receive credentials from a remote client computer.
On the remote machine, you enable the server role:
£> Enable-WSManCredSSP -Role server -Force
cfg : http://schemas.microsoft.com/wbem/wsman/1/config/service/auth
lang : en-US
Basic : false
Kerberos : true
Negotiate : true
Certificate : false
CredSSP : true
CbtHardeningLevel : Relaxed
Compare the information from the two commands. The client has all options enabled, but the server is more limited in its authentication options. Again, you can verify the settings:
£> Get-WSManCredSSP
The machine is not configured to allow delegating fresh credentials.
This computer is configured to receive credentials from a remote client computer.
Now re-create the remote session to use CredSSP:
$cred = Get-Credential
$sessw12 = New-PSSession -ComputerName win12r2 -Authentication credssp -Credential $cred
You can then use the session as normal against the remote machine:
Invoke-Command -Session $sessw12 -ScriptBlock {get-service}
You can also utilize the second hop and your CredSSP configuration to access other machines from the target machine:
Invoke-Command -Session $sessw12 -ScriptBlock {get-service -ComputerName w08r2sql08}
Now comes the big question. Just because I can, does it mean I should?
I would recommend against routinely working over the second hop. It weakens the security in your domain because credential delegation is blocked by default. If you find yourself using CredSSP, I would recommend thinking about if there is a better way. If not, use it with care, and remember to disable CredSSP after you have finished.
Using HTTPS
The second topic on the list is using HTTPS instead of HTTP. This also raises a fair amount of discussion, and I would only see a need for this in a minority of cases. There are a number of steps you need to go through to enable remoting over HTTPS:
- Obtain an SSL certificate for the server, and make sure it is issued to the FQDN of the host server
- Install the SSL certificate in the computer’s certificate store (not in the user’s store)
- Create a new WSMAN listener for HTTPS as follows:
> New-WSManInstance -ResourceURI winrm/config/Listener -SelectorSet @{Transport='HTTPS', Address="IP:10.10.54.59"} -ValueSet @{Hostname="Win12R2.Manticore.org", CertificateThumbprint="XXXXXXX"}
…where XXXXXXX is the thumbprint of the certificate.
You then connect to the remote server from your client:
$sess = New-PSSession –ComputerName = Win12R2 –UseSSL
Configuring endpoints
The final topic for this part of the series is configuring endpoints. This is another area where you have a lot of options; but in reality, you won’t be using many of them. In my experience, and that of my co-authors of PowerShell in Depth, 99.99% of the time, the standard remoting endpoint configurations will be what you want. The configuration options are for the odd time you step outside of the norm.
How are the standard endpoints configured?
£> Get-PSSessionConfiguration
Name : microsoft.powershell
PSVersion : 4.0
StartupScript :
RunAsUser :
Permission : BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed
This is the standard endpoint that you connect to for remoting. The other standard endpoints in later versions of Windows are:
microsoft.powershell
microsoft.powershell.workflow
microsoft.powershell32
microsoft.windows.servermanagerworkflows
The names explain their purposes rather well. The full configuration of the default endpoint is:
Architecture : 64
Filename : %windir%\system32\pwrshplugin.dll
ResourceUri : http://schemas.microsoft.com/powershell/microsoft.powershell
MaxConcurrentCommandsPerShell : 1000
Capability : {Shell}
xmlns : http://schemas.microsoft.com/wbem/wsman/1/config/PluginConfiguration
MaxConcurrentUsers : 5
Name : microsoft.powershell
SupportsOptions : true
ProcessIdleTimeoutSec : 0
ExactMatch : False
RunAsUser :
IdleTimeoutms : 7200000
OutputBufferingMode : Block
PSVersion : 4.0
SecurityDescriptorSddl : O:NSG:BAD:P(A;;GA;;;BA)(A;;GA;;;RM)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)
MaxShellsPerUser : 25
AutoRestart : false
MaxShells : 25
MaxIdleTimeoutms : 2147483647
Uri : http://schemas.microsoft.com/powershell/microsoft.powershell
SDKVersion : 2
XmlRenderingType : text
RunAsPassword :
MaxProcessesPerShell : 15
ParentResourceUri : http://schemas.microsoft.com/powershell/microsoft.powershell
Enabled : true
UseSharedProcess : false
MaxMemoryPerShellMB : 1024
lang : en-US
Permission : BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed
Having said that, what can you do? You can:
- Create a restricted language endpoint (only a small subset of the Windows PowerShell language is available)
- Create a No-Language endpoint (you can’t use any of the Windows PowerShell language; you can only run cmdlets)
- Restrict who can access the endpoint
- Restrict which modules can be loaded into the endpoint
- Define the environment variables to load into the endpoint
- Define the aliases to be available through the endpoint
- Define the execution policy
- Define the Windows PowerShell version
- Define scripts to run on connection to the endpoint
- Define the session type:
Empty: Nothing is loaded.
Default: Windows PowerShell core commands plus your definitions are loaded.
Restricted: Seven basic commands, plus what you’ve defined are loaded.
Create the definition file for the endpoint by using New-PSSessionConfigurationFile. You then create the endpoint by using Register-PSSessionConfiguration.
For more information, see the Help files for:
New-PSSessionConfigurationFile
Register-PSSessionConfiguration
about_Session_Configurations
about_Session_Configuration_Files
Also, you can discover more about configuring remoting and some other edge cases in Chapter 10 of PowerShell in Depth by myself, Don Jones, and Jeffery Hicks.
Bye for now.
~Richard
Thanks, Richard. This is a very informative series.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy