Public/Get-ALHADCircularNestedGroup.ps1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
<#PSScriptInfo
.VERSION 1.0.0 .GUID 27db6c7c-0d12-4235-8ac8-0ba11affcd01 .AUTHOR Dieter Koch .COMPANYNAME .COPYRIGHT (c) 2021-2023 Dieter Koch .TAGS .LICENSEURI https://github.com/admins-little-helper/ALH/blob/main/LICENSE .PROJECTURI https://github.com/admins-little-helper/ALH .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES 1.0.0 Initial release #> <# .DESCRIPTION Contains a function to find circular nested groups in Active Directory. .LINK https://github.com/admins-little-helper/ALH #> function Get-ALHADCircularNestedGroup { <# .SYNOPSIS Find circular nested groups in Active Directory. .DESCRIPTION The 'Get-ALHADCircularNestedGroup' function searches for instances of circular nested groups in Active Directory. Sometimes it happens that circular nested groups get created accidentally. For example GroupA has GroupB as member. GroupB has GroupC as member. And GroupC has GroupA as member. This function helps to identify these conflicts. .PARAMETER SearchBase One ore more names of organizational unites to search in recursively for nested groups. If not specified, the entire domain will be searched. .EXAMPLE Get-ALHADCircularNestedGroup -SearchBase 'OU=Groups,DC=contoso,DC=com' -Verbose Find all circular groups in two different organizational units and show verbose messages. .EXAMPLE Get-ALHADCircularNestedGroup Find all circular groups in the domain. .INPUTS System.String for parameter 'SearchBase' .OUTPUTS PSCustomObject .NOTES Author: Dieter Koch Email: diko@admins-little-helper.de .LINK https://github.com/admins-little-helper/ALH/blob/main/Help/Get-ALHADCircularNestedGroup.txt #> [CmdLetBinding()] param ( [Parameter(ValueFromPipeline)] [String[]]$SearchBase ) begin { $StartDateTime = Get-Date if ( [string]::IsNullOrEmpty($SearchBase)) { try { $Domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() Write-Verbose "Searching for groups in entire AD domain '$($Domain.Name)'" $SearchBase = ($Domain.GetDirectoryEntry()).DistinguishedName } catch { $_ break } } } process { foreach ($SearchBaseElement in $SearchBase) { try { Write-Verbose -Message "Trying to get groups from AD..." $AllGroups = Get-ALHADGroupMemberHT -SearchBase $SearchBaseElement Write-Verbose "# Groups found $(($AllGroups | Measure-Object).Count)" } catch { throw "Failed getting circular group membership: $_" } try { $GroupMembers = @{} # Enumerate groups and populate hashtable. # The key value will be the Distinguished Name of the group. # The item value will be an array of the Distinguished Names of all members of the group that are groups. # The item value starts out as an empty array, since we don't know yet which members are groups. foreach ($Group in $AllGroups) { $DN = [String]$Group.properties.Item('distinguishedName') Write-Debug -Message "Adding group with DN to hashtable: $DN" $GroupMembers.Add($DN, @()) } # Now enumerate the groups again to populate the item value arrays. foreach ($Group in $AllGroups) { $DN = [String]$Group.properties.Item('distinguishedName') $Members = @($Group.properties.Item('member')) foreach ($Member in $Members) { If ($GroupMembers.ContainsKey($Member)) { Write-Debug -Message "Adding member to group --> $DN" Write-Debug -Message "Group member -->--> $Member" $GroupMembers[$DN] += $Member } } } $NestedGroups = foreach ($Group in $GroupMembers.Keys) { Get-ALHNestetdGroup -Identity $Group -Parent @($Group) -GroupMember $GroupMembers } $NestedGroups Write-Verbose -Message "Found '$(($NestedGroups | Measure-Object).Count)' nested groups in $SearchBaseElement" } catch { throw "Failed retrieving circular group membership: $_" } } } end { Write-Verbose -Message "Search finished" Write-Verbose -Message "Elapes time in seconds: $($(Get-Date) - $StartDateTime)" } } #region EndOfScript <# ################################################################################ ################################################################################ # # ______ _ __ _____ _ _ # | ____| | | / _| / ____| (_) | | # | |__ _ __ __| | ___ | |_ | (___ ___ _ __ _ _ __ | |_ # | __| | '_ \ / _` | / _ \| _| \___ \ / __| '__| | '_ \| __| # | |____| | | | (_| | | (_) | | ____) | (__| | | | |_) | |_ # |______|_| |_|\__,_| \___/|_| |_____/ \___|_| |_| .__/ \__| # | | # |_| ################################################################################ ################################################################################ # created with help of http://patorjk.com/software/taag/ #> #endregion |