List AD group members when the group contains foreign security principals

Written by Luke Arntz on November 20, 2019
[ Windows ] [ PowerShell ]

Contents

List AD Group Members

Getting an active directory group’s member list is as simple as Get-ADGroupMember if the group only has members from the current domain. However, if you need to get group members for a group that has foreign security principals (users from another domain) things get a bit more complicated. Even more so when some of those objects have been orphaned.

If you’re lucky you’ll end up with a user list that contains SID’s from another domain mixed with users from the local domain. At other times, you may get an unspecified error.

PS C:\Users\administrator> Get-ADGroupMember example_group
Get-ADGroupMember : An unspecified error has occurred
At line:1 char:1
+ Get-ADGroupMember example_group
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (retail_merch_prod:ADGroup) [Get-ADGroupMember], ADException
    + FullyQualifiedErrorId : ActiveDirectoryServer:0,Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember

Translating Foreign Security Principals

To get actual user names from the SID’s well need to use the translate() function from the .NET [System.Security.Principal.SecurityIdentifier] type.

Function to List Users

Here the function I use to get members of groups with foreign security principals.

function Get-AdGroupForeignMembers
{
    param(
        [string]$group
    )

    $translatedMembers = @()

    $members = (Get-ADGroup $group -Properties member).member
    foreach($m in $members)
    {
        $orphan = $false
        $name = ""
        $dn = $([adsi]$("LDAP://$m")).DistinguishedName
        $ado = Get-ADObject -Identity $($dn)
        if($ado.Name -match "^S-\d-\d-\d\d")
        {
            
            try 
            {
                $name =  ([System.Security.Principal.SecurityIdentifier] $ado.Name).Translate([System.Security.Principal.NTAccount])
            }
            catch 
            {
                $name = $ado.Name
                $orphan = $true
            }

        }
        else 
        {
                $name = $ado.Name
        }

        $translatedMembers += [PSCustomObject] @{
            Name = $name
            Orphaned = $orphan
        }
    }

    Write-Output $translatedMembers
}

References

Related Articles

Top