Public/Objects/Get-ADGroupsAndMembers.ps1
|
function Get-ADGroupsAndMembers { [CmdletBinding()] param( [string]$ObjectType = "Groups", [string]$ExportPath = $script:Config.ExportPath ) try { Write-Log "Retrieving groups and members..." -Level Info Show-ProgressHelper -Activity "AD Inventory" -Status "Initializing group retrieval..." $properties = @( 'Name', 'Description', 'GroupCategory', 'GroupScope', 'Members', 'MemberOf', 'AdminCount', 'DistinguishedName', 'Created', 'Modified' ) $groups = Invoke-WithRetry -ScriptBlock { Get-ADGroup -Filter * -Properties $properties -ErrorAction Stop } $groupObjects = Get-ADObjects -ObjectType $ObjectType -Objects $groups -ProcessingScript { param($group) try { # Get nested group membership recursively $allMembers = Get-ADGroupNestedMembers -Group $group # Determine if this is a privileged group $isPrivileged = $group.AdminCount -eq 1 -or $group.Name -in @('Domain Admins', 'Enterprise Admins', 'Schema Admins') [PSCustomObject]@{ Name = $group.Name Description = $group.Description GroupCategory = $group.GroupCategory # Security or Distribution GroupScope = $group.GroupScope # Universal, Global, DomainLocal IsPrivileged = $isPrivileged DirectMemberCount = ($group.Members | Measure-Object).Count TotalNestedMemberCount = ($allMembers | Measure-Object).Count Members = $allMembers | ForEach-Object { [PSCustomObject]@{ Name = $_.Name ObjectClass = $_.ObjectClass DistinguishedName = $_.DistinguishedName MemberType = if ($_.ObjectClass -eq 'group') { 'NestedGroup' } else { 'DirectMember' } } } ParentGroups = $group.MemberOf | ForEach-Object { Get-ADGroup $_ | Select-Object -ExpandProperty Name } Created = $group.Created Modified = $group.Modified DistinguishedName = $group.DistinguishedName AccessStatus = "Success" } } catch { Write-Log "Error processing group $($group.Name): $($_.Exception.Message)" -Level Warning [PSCustomObject]@{ Name = $group.Name Description = $group.Description GroupCategory = $group.GroupCategory GroupScope = $group.GroupScope IsPrivileged = $false DirectMemberCount = 0 TotalNestedMemberCount = 0 Members = @() ParentGroups = @() Created = $group.Created Modified = $group.Modified DistinguishedName = $group.DistinguishedName AccessStatus = "Access Error: $($_.Exception.Message)" } } } return $groupObjects } catch { Write-Log "Error retrieving groups: $($_.Exception.Message)" -Level Error Show-ErrorBox "Unable to retrieve groups. Check permissions." } } # Helper function to get nested group members recursively function Get-ADGroupNestedMembers { param( [Parameter(Mandatory)] [Microsoft.ActiveDirectory.Management.ADGroup]$Group, [System.Collections.ArrayList]$ProcessedGroups = @() ) if ($ProcessedGroups -contains $Group.DistinguishedName) { return @() } [void]$ProcessedGroups.Add($Group.DistinguishedName) $members = foreach ($member in $Group.Members) { $obj = Get-ADObject $member -Properties objectClass, name, distinguishedName if ($obj.objectClass -eq 'group') { $obj Get-ADGroupNestedMembers -Group (Get-ADGroup $obj -Properties Members) -ProcessedGroups $ProcessedGroups } else { $obj } } return $members } |