Search code examples
powershellinvoke-command

Enumerating local groups using Invoke-Command on remote machines


I have an issue with a function I've wrote to return members of local groups when it is run against a remote machine. We use secondary domain accounts for admin privileges so I've used Invoke-Command so we can run the script block with that account, however, when I do this as opposed to running a new PowerShell window with my admin credentials, it can't enumerate members of the local group that aren't local users.

$computers = "blah"
$creds = Get-Credential
$sb = {
    param($c)
    Add-Type -AssemblyName System.DirectoryServices.AccountManagement
    $ctype = [System.DirectoryServices.AccountManagement.ContextType]::Machine
    $context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList $ctype,$c
    $idtype = [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName
    $lg = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($context,$idtype,"administrators")
    $members = $lg.Members
    return $members
}

foreach ($c in $computers) {
    if ($c -eq $env:COMPUTERNAME) { & $sb -c $c }
    else {
        Invoke-Command -ComputerName $c -Credential $creds -ScriptBlock $sb -ArgumentList $c
    }
}

When run against a machine that I'm logged in to locally it returns all members of the local group. It also works if I start a new console with my second account. If credentials are passed with Invoke-Command though, I receive errors pertaining to a lack of network access and it appears to happen after successfully listing the two local accounts on a machine first.

Information returned for lg variable when failing:

PSComputerName        : blah
RunspaceId            : hex...
IsSecurityGroup       : True
GroupScope            : Local
Members               : {local_admin, local_user}
Context               : System.DirectoryServices.AccountManagement.PrincipalContext
ContextType           : Machine
Description           : Administrators have complete and unrestricted access to the computer/domain
DisplayName           :
SamAccountName        : Administrators
UserPrincipalName     :
Sid                   : SID...
Guid                  :
DistinguishedName     :
StructuralObjectClass :
Name                  : Administrators

When it's successful, the Members section includes domain groups and users too (identical results if remotely with shell run as second account or locally on the server logged on as second account):

IsSecurityGroup       : True
GroupScope            : Local
Members               : {local_admin, local_user, domain_group, domain_group, domain_user...}
Context               : System.DirectoryServices.AccountManagement.PrincipalContext
ContextType           : Machine
Description           : Administrators have complete and unrestricted access to the computer/domain
DisplayName           :
SamAccountName        : Administrators
UserPrincipalName     :
Sid                   : SID...
Guid                  :
DistinguishedName     :
StructuralObjectClass :
Name                  : Administrators

Two different errors received with slightly different approaches:

An error occurred while enumerating through a collection: The network path was not found.
.
    + CategoryInfo          : InvalidOperation: (System.Director...ctionEnumerator:PrincipalCollectionEnumerator) [], RuntimeException
    + FullyQualifiedErrorId : BadEnumeration
    + PSComputerName        : blah

Cannot convert value "System.DirectoryServices.AccountManagement.PrincipalCollection" to type "System.Array". Error: "The network path was not found.
"
    + CategoryInfo          : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException
    + PSComputerName        : blah

The first message is from just trying to return the members variable, the second one was when I tried to make that variable an array. I think they essentially have the same root cause. I tried adding the -EnableNetworkAccess switch to Invoke-Command, but this doesn't change the error received.

I appreciate that I already know a way to make this work, but we'd like to see if there is any way around running the shell with admin credentials and only introducing them when they need to be passed for remote servers. It doesn't appear to be an authentication issue because we can run more simple commands using Invoke-Command i.e. ipconfig or whoami.

I'm using PowerShell 5.1

Thanks.


Solution

  • PoSH remoteing requires the account to be a local admin on the target host, with the exception of the commands listed below. Is this...

    'We use secondary domain accounts for admin privileges'

    ... a local admin?

    https://technet.microsoft.com/en-us/library/ff699046.aspx Some cmdlets have a –ComputerName parameter that lets you work with a remote computer without using Windows PowerShell remoting. This means you can use the cmdlet on any computer that is running Windows PowerShell, even if the computer is not configured for Windows PowerShell remoting. These cmdlets include the following

    If you are trying to remote across domain, you are going to get hit with the Windows double hop restriction and you'll need to plan and configure for that type of scenario. See the below.

    https://blogs.msdn.microsoft.com/clustering/2009/06/25/powershell-remoting-and-the-double-hop-problem An Easy “Double-Hop” Solution

    You can use CredSSP to delegate your credentials to the remote computer so every remote access from the remote machine will also work. To enable this, you will need to run (from an elevated command prompt) the following command on the client machine:

    Or this option...

    https://blogs.technet.microsoft.com/ashleymcglone/2016/08/30/powershell-remoting-kerberos-double-hop-solved-securely Are you facing issues with PowerShell remoting and credentials? You remote into your jump box, but then any remoting beyond there gets a big red ACCESS DENIED. Maybe you’ve tried CredSSP, but people say that isn’t safe. Read today’s post for a completely legit, secure, safe, and easy way to enable Kerberos double hop for PowerShell remoting.