0

I often use PowerShell remote sessions to manage windows servers remotely, generally using the following command, though the following is true for any remote powershell commands such as Invoke-Command:

Enter-PSSession Server01

This works perfectly for almost everything local to that server, but never allows you to reach outside, e.g.:

PS C:\> Enter-PSSession Server01
[Server01]: PS C:\> Get-Item '\\Server02\Share\File'

get-item : Access is denied

What is the easiest, secure way to do a second-hop like this? I have a couple answers I'll add, but they generally have caveats.

Cpt.Whale
  • 297
  • 1
  • 10

3 Answers3

1

Use Kerberos constrained delegation to allow Server01 to be able to authenticate you to Server02:

Set-ADComputer 'Server02' -PrincipalsAllowedToDelegateToAccount (Get-ADComputer 'Server01')

And some pros/cons from the linked Microsoft doc and myself:

Pros

  • Credentials are not stored.
  • One-liner to set up.
  • Stays configured indefinitely.
  • One command to cleanup:
    • Set-ADComputer -Identity 'Server02' -PrincipalsAllowedToDelegateToAccount $null
  • An AD admin can configure on behalf of someone else.

Cons

  • Requires Windows Server (and Domain Level) 2012 or later.
  • Does not support the second hop for WinRM.
  • Requires rights to update objects and Service Principal Names (SPNs) in Active Directory.
  • May not take effect immediately due to AD replication times or the KDC cache (see the link).
  • Always applies to all users.

To find existing delegations (or ones you've forgotten to remove) run this to return a list:

Get-ADComputer -Filter 'msDS-AllowedToActOnBehalfOfOtherIdentity -like "*"' -Properties msDS-AllowedToActOnBehalfOfOtherIdentity | Select Name,@{l='AllowedFrom';e={$_.'msDS-AllowedToActOnBehalfOfOtherIdentity'.Access.IdentityReference.Value}}
Cpt.Whale
  • 297
  • 1
  • 10
0

Save a credential to a PSSessionConfiguration object with the following command:

Invoke-Command -ComputerName 'Server01' -ScriptBlock { 
  Register-PSSessionConfiguration -Name 'MyUser' -RunAsCredential 'MyDomain\MyUser'
}

Then use that configuration to connect and hop:

PS C:\> Enter-PSSession -ComputerName Server01 -ConfigurationName MyUser
[Server01] PS C:\> Get-Item '\\Server01\Share\File'

# Successful

Pros:

  • Technically a one-liner to set up
  • Can also clean up entirely in one line when you're done:
    • Invoke-Command -ComputerName Server01 -ScriptBlock {Unregister-PSSessionConfiguration 'MyUser'}
  • Credentials are encrypted

Cons:

  • Credentials are stored on remote computer in reversible format, and can be stolen by someone with administrator access.
  • This configuration stops working when you change the password. (You shouldn't leave credentials lying around anyways)
  • Setting a new configuration requires restarting the WinRM service for it to be usable, which ends any existing sessions. (This can be done automatically by adding the -Force flag to Register-PSSessionConfiguration)
Cpt.Whale
  • 297
  • 1
  • 10
0

Pass credential object through remote variables:

$cred = Get-Credential
Invoke-Command -ComputerName Server01 -Credential $cred -ScriptBlock {
    Invoke-Command -ComputerName Server02 -Credential $Using:cred -ScriptBlock {hostname}
}

Pros:

  • Nothing to set up ahead of time.
  • Nothing is saved on the remote servers.

Cons:

  • $Using variables are only available with Invoke-Command, and not in PowerShell sessions.
  • Requires cmdlets with a -credentials flag. Copy-Item doesn't have one, but Start-BitsTransfer does, so it may take some digging.
Cpt.Whale
  • 297
  • 1
  • 10