Search code examples
powershellpowershell-remoting

Cross-Domain Remoting - Issues determining which credentials to use


I am working on a script that will be running remote PowerShell on a large list of servers, these servers may randomly change domains. So, for instance, a list might have 50 servers on domain A and 150 servers on domain B.

I have been successful in executing this script via using wildcards/regex to determine which domain the server is joined to.

That being said, using names is an awful solution, and I would like to find a better way to determine the correct credentials to use. I would like to avoid using Invoke-Command just to test the connection. The best solution I have found is to use something akin to the following:

try {
    $session = New-PSSession -Credential $a -ComputerName $_ -ErrorAction Stop
} catch {
    $session = New-PSSession -Credential $b -ComputerName $_
}

In this case, $_ is simply a string, a computer name. The credential objects are defined via Get-Credential.

I feel like this could be much more efficient, in theory. Additionally, it simply does not work. While me using if/else with the exact same contents functions perfectly, the code in catch always fails with:

New-PSSession : One or more computer names are not valid.

This does not make much sense to me, since the syntax I use functions perfectly everywhere outside catch. For instance, in the above example, the code in try works. Swapping the contents of each block still results in failure of catch. I have also tried using Remove-PSSession $session, however that did not seem to help.

So my question is:

  1. Is this even the best way to accomplish this task?
  2. If it is, why does my catch block inexplicably fail?

Solution

  • You could use a DNS lookup to get the FQDN from the hostname, remove the hostname from the FQDN to get the domain name, then lookup the credentials by the domain name in a hashtable.

    $credentials = @{
        'example.com' = $a
        'example.com' = $b
        ...
    }
    
    ...
    
    $serverList | ForEach-Object {
        $fqdn = [Net.Dns]::GetHostByName($_) | Select-Object -Expand HostName
        $null, $domain = $fqdn -split '\.', 2
        $cred = $credentials[$domain]
    
        $session = New-PSSession -Credential $cred -ComputerName $fqdn
        ...
    }