0

I am writing a custom function to get active directory group members. The reason I write it but not use Get-ADGroupMember or Get-QADGroupMember because I want to track the relations between the nested groups within nested groups. The standard function doesn't have it.

Function Get-GrpMmbr {
    param([string]$Identity, [string]$Domain)
    $Members = Get-ADGroupMember -Identity $Identity -Server $Domain
    # Pipe through all members. If it is group, then dump info and call itself;
    # Else (not group), dump info.
    $Members | foreach {
        if ($_.objectClass -eq 'group') {
            # Get the groupName and domain name
            $DistinguishedName = $_.distinguishedName
            $Parts = $DistinguishedName -split ","
            foreach ($Part in $parts) {
                if($Part -like "CN=*"){$GroupName = ($Part -split "=")[1]}
                if($Part -like "DC=*"){$DomainName=($Part -split "=")[1];break}
            }
            [PSCustomObject]@{
                'UserName' = $_.name
                'UserID' = $_.SamAccountName
                'GroupName' = $Identity ## show the group from the direct parent group
                'Type'= "Group"
            } # end of new object
            # recursion happens here
            Get-EFSGrpMmbr -Identity $GroupName -Domain $DomainName
        } else {
            [PSCustomObject]@{
                'UserName' = $_.name
                'UserID' = $_.SamAccountName
                'GroupName' = $Identity
                'Type' = "User"
            } # end of new object
        } # end of Else
    } # end of foreach loop
} # end of function

Problem: it gets into infinite loop with following scenario:

Get-GrpMmbr -Identity 'GroupA' -Domain 'NW'

Condition is: GroupA is member of GroupB; GroupB is member of GroupC; GroupC is member of GroupA.

So, how to stop the infinite loop?

8
  • Confused by the call to Get-EFSGrpMmbr. Is that a different function, or an alias for Get-GrpMmber? Commented May 4, 2017 at 0:30
  • Sure, the is a little confusing. it can change to be whatever you like. That's not my problem indicated. Commented May 4, 2017 at 0:33
  • 3
    [System.Collections.ArrayList]$Global:CompletedGroups = @(). .Add() group names to it as they are processed, check if ($GroupName -in it) before making the recursive call. Commented May 4, 2017 at 1:20
  • 2
    It would also be a good idea to report such circular relations as they're really not a good idea. Commented May 4, 2017 at 8:48
  • 1
    @TessellatingHeckler I think passing the list of "parent groups" as a parameter might be a cleaner approach than modifying a global variable. Commented May 4, 2017 at 10:23

1 Answer 1

1
Function Get-GrpMmbr {
    param([string]$Identity, [string]$Domain, [array]$Path = @())
    If ($Path -contains $Identity) {Return}
    ...
    Get-GrpMmbr $GroupName $DomainName ($Path + $Identity)
    ...
}

And if you want to display the infinite loop:

Function Get-GrpMmbr {
    param([string]$Identity, [string]$Domain, [array]$Path = @())
    $i = [array]::indexof($Path, $Identity)     #In case of a sAMAccountName you might want to ignore the case
    If ($i -ge 0) {
        Write-Host "Inifitive loop:" $Path[$i..999]
        Return
    }
    ...
    Get-GrpMmbr $GroupName $DomainName ($Path + $Identity)
    ...
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.