# ------------------------------------------------------------------ # 1. Set up environment # ------------------------------------------------------------------ $ComputerName = "FRRF1LLC1103011" $printDebug = $false Import-Module GroupPolicy -ErrorAction Stop Import-Module ActiveDirectory -ErrorAction Stop # ------------------------------------------------------------------ # 2. Resolve the computer’s DN and build the OU chain (leaf → root) # ------------------------------------------------------------------ try { $comp = Get-ADComputer -Identity $ComputerName -Properties DistinguishedName } catch { Write-Error "Cannot find computer '$ComputerName' in AD: $_" exit 1 } $ouDN = $comp.DistinguishedName -replace '^CN=.*?,', '' $ouChain = @() $currentDN = $ouDN while ($currentDN -match '^OU=') { $ouChain += $currentDN $currentDN = $currentDN.Substring($currentDN.IndexOf(',') + 1) } $ouChain += $currentDN # root if ($printDebug) { Write-Host "OU chain (leaf → root):" -ForegroundColor Cyan $ouChain | ForEach-Object { Write-Host $_ } } # ------------------------------------------------------------------ # 3. Gather GPO links for each OU in the chain # ------------------------------------------------------------------ $gpoLinks = @{} # Hashtable: GPO_GUID => array of OU DNs foreach ($ouDN in $ouChain) { try { $ouObj = Get-ADObject -Identity $ouDN -Properties gPLink -ErrorAction Stop } catch { Write-Warning "Could not read OU '$ouDN': $_" continue } if ($ouObj.gPLink) { foreach ($link in ($ouObj.gPLink -split ';')) { $clean = $link.Trim(' ', '[', ']') if ($clean -match '\{(?[0-9a-fA-F-]+)\}') { $guid = $Matches.guid if (-not $gpoLinks.ContainsKey($guid)) { $gpoLinks[$guid] = @() } $gpoLinks[$guid] += $ouDN } } } } if (-not $gpoLinks.Count) { Write-Host "No GPOs linked to any OU in the hierarchy." -ForegroundColor Yellow exit } Write-Host "Found $($gpoLinks.Count) distinct GPO(s) linked in this OU tree." -ForegroundColor Green # ------------------------------------------------------------------ # 4. Collect all restricted‑group entries into an array # ------------------------------------------------------------------ $results = @() # Will hold objects: @{ADGroup=; LocalGroup=; GPO=} $uniqueGpoGuids = $gpoLinks.Keys | Sort-Object -Unique $ou_counter = 0 $totalItems = $uniqueGpoGuids.Count $startTime = Get-Date foreach ($gpoGuid in $uniqueGpoGuids) { $ou_counter++ try { $gpo = Get-GPO -Guid $gpoGuid -ErrorAction Stop } catch { Write-Warning "Unable to retrieve GPO $gpoGuid – skipping."; continue } $percentComplete = [int]( ($ou_counter / $gpoLinks.Count) * 100 ) if ($ou_counter -gt 0) { $elapsed = (Get-Date) - $startTime $averagePerItem = $elapsed.TotalSeconds / $ou_counter $remainingItems = $totalItems - $ou_counter $secondsRemaining = [int]($averagePerItem * $remainingItems) } else { $secondsRemaining = -1 } Write-Progress -Activity "Processing GPOs" ` -Status $gpo.DisplayName ` -PercentComplete $percentComplete ` -SecondsRemaining $secondsRemaining ` -CurrentOperation "GPO $ou_counter of $totalItems" # Grab XML report try { $xmlString = Get-GPOReport -Guid $gpoGuid -ReportType Xml -ErrorAction Stop } catch { Write-Warning "Unable to generate XML report for $($gpo.DisplayName)."; continue } $xml = [xml]$xmlString $ns = New-Object System.Xml.XmlNamespaceManager ($xml.NameTable) $ns.AddNamespace('m', 'http://www.microsoft.com/GroupPolicy/Settings') $ns.AddNamespace('q1', 'http://www.microsoft.com/GroupPolicy/Settings/Security') $ns.AddNamespace('t', 'http://www.microsoft.com/GroupPolicy/Types') $ns.AddNamespace('xsi','http://www.w3.org/2001/XMLSchema-instance') $restrictedGroups = $xml.SelectNodes('//q1:RestrictedGroups', $ns) foreach ($rg in $restrictedGroups) { $adGroupName = ($rg.SelectSingleNode('q1:GroupName/t:Name', $ns)).InnerText $localGroupName = ($rg.SelectSingleNode('q1:Memberof/t:Name', $ns)).InnerText $results += [pscustomobject]@{ ADGroup = $adGroupName LocalGroup = $localGroupName GPO = $gpo.DisplayName } } } $elapsed = (Get-Date) - $startTime $elapsedSeconds = [math]::Round($elapsed.TotalSeconds, 2) Write-Host "`nFinished processing $totalItems GPO(s) after $elapsedSeconds seconds." -ForegroundColor Green # ------------------------------------------------------------------ # 5. Print two separate lists # ------------------------------------------------------------------ Write-Host "`n=== AD groups that are members of BUILTIN\Administrators ===" -ForegroundColor Yellow $results | Where-Object {$_.LocalGroup -eq 'BUILTIN\Administrators'} | Select-Object -ExpandProperty ADGroup | Sort-Object | Get-Unique Write-Host "`n=== AD groups that are members of vnc_admin ===" -ForegroundColor Yellow $results | Where-Object {$_.LocalGroup -eq 'vnc_admin'} | Select-Object -ExpandProperty ADGroup | Sort-Object | Get-Unique