132 lines
4.8 KiB
PowerShell
132 lines
4.8 KiB
PowerShell
# ------------------------------------------------------------------
|
||
# 0. Load modules (they are usually loaded by default, but be safe)
|
||
# ------------------------------------------------------------------
|
||
|
||
Import-Module GroupPolicy -ErrorAction Stop
|
||
Import-Module ActiveDirectory -ErrorAction Stop
|
||
$TargetOU = "OU=NA,OU=Manufacturing,OU=Tesla Systems,DC=teslamotors,DC=com"
|
||
$OutputFile = "C:\Users\matanderson\gpo\gpo-update.yaml"
|
||
# Add-Content -Path $OutputFile -Value $line
|
||
if (Test-Path $OutputFile) {
|
||
Remove-Item -Path $OutputFile -Force
|
||
}
|
||
|
||
# ------------------------------------------------------------------
|
||
# 1. Grab every OU under $TargetOU (including $TargetOU itself)
|
||
# ------------------------------------------------------------------
|
||
|
||
Write-Output "Enumerating OUs under '$TargetOU' ..."
|
||
Add-Content -Path $OutputFile -Value "---"
|
||
Add-Content -Path $OutputFile -Value "- root_ou: $TargetOU"
|
||
$Start_Date = (Get-Date).ToString('MM/dd/yyyy hh:mm:ss tt')
|
||
Add-Content -Path $OutputFile -Value " init_timestamp: $Start_Date"
|
||
$ouObjects = Get-ADObject `
|
||
-Filter 'ObjectClass -eq "organizationalUnit"' `
|
||
-SearchBase $TargetOU `
|
||
-SearchScope Subtree `
|
||
-Properties gPLink
|
||
|
||
# Also grab the target OU itself (in case it is linked directly)
|
||
$targetOUObj = Get-ADObject `
|
||
-Identity $TargetOU `
|
||
-Properties gPLink
|
||
if ($targetOUObj) {
|
||
$ouObjects += $targetOUObj
|
||
}
|
||
|
||
# ------------------------------------------------------------------
|
||
# 2. Build a hashtable: GPO_GUID => list of OU DNs it is linked to
|
||
# ------------------------------------------------------------------
|
||
|
||
$gpoLinks = @{}
|
||
|
||
foreach ($ou in $ouObjects) {
|
||
if ($ou.gPLink) {
|
||
foreach ($link in ($ou.gPLink -split ';')) {
|
||
$linkTrim = $link.Trim('[', ']')
|
||
if ($linkTrim -match '\{(?<guid>[0-9a-fA-F-]+)\}') {
|
||
$guid = $Matches.guid
|
||
if (-not $gpoLinks.ContainsKey($guid)) {
|
||
$gpoLinks[$guid] = @()
|
||
}
|
||
$gpoLinks[$guid] += $ou.DistinguishedName
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (-not $gpoLinks.Count) {
|
||
Write-Host "No GPOs linked under the searched OU tree." -ForegroundColor Yellow
|
||
exit
|
||
}
|
||
|
||
|
||
|
||
Write-Host "Found $($gpoLinks.Count) distinct GPO(s) linked in the OU tree."
|
||
Add-Content -Path $OutputFile -Value " gpo_links: $($gpoLinks.Count)"
|
||
|
||
# ----------------------------------------------------
|
||
# 3. For each GPO, get an XML report and pull RestrictedGroup nodes
|
||
# ----------------------------------------------------
|
||
|
||
|
||
Add-Content -Path $OutputFile -Value " configured_gpos:"
|
||
$ou_counter = 0
|
||
foreach ($gpoGuid in $gpoLinks.Keys) {
|
||
$ou_counter++
|
||
|
||
try {
|
||
$gpo = Get-GPO -Guid $gpoGuid -ErrorAction Stop
|
||
}
|
||
catch {
|
||
Write-Warning "Unable to retrieve GPO $gpoGuid – skipping."
|
||
continue
|
||
}
|
||
Write-Host "GPO $ou_counter of $($gpoLinks.Count): $($gpo.DisplayName)"
|
||
Add-Content -Path $OutputFile -Value " $($gpo.DisplayName):"
|
||
# ok, i need to start generating a variable with all links in it
|
||
|
||
|
||
# -------- Linked OUs ----------
|
||
$linkedOUs = $gpoLinks[$gpoGuid] # <-- the list we built earlier
|
||
Add-Content -Path $OutputFile -Value " - Linked_OUs:"
|
||
foreach ($ouDn in $linkedOUs) {
|
||
Add-Content -Path $OutputFile -Value " - $ouDn"
|
||
}
|
||
|
||
|
||
# Pull the 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') # default namespace
|
||
$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')
|
||
|
||
# Find every <q1:RestrictedGroups> element
|
||
$restrictedGroups = $xml.SelectNodes('//q1:RestrictedGroups', $ns)
|
||
|
||
# Loop and build the string
|
||
foreach ($rg in $restrictedGroups) {
|
||
$adGroupName = ($rg.SelectSingleNode('q1:GroupName/t:Name', $ns)).InnerText
|
||
$localGroupName = ($rg.SelectSingleNode('q1:Memberof/t:Name', $ns)).InnerText
|
||
$plainAD_Groupname = ($adGroupName -split '\\')[-1]
|
||
#Write-Output "AD Group: $adGroupName - Local Group: $localGroupName"
|
||
Add-Content -Path $OutputFile -Value " - ad_group: $plainAD_Groupname"
|
||
Add-Content -Path $OutputFile -Value " local_group: $localGroupName"
|
||
}
|
||
Add-Content -Path $OutputFile -Value ""
|
||
}
|
||
$Current_Date = (Get-Date).ToString('MM/dd/yyyy hh:mm:ss tt')
|
||
Add-Content -Path $OutputFile -Value " timestamp: $Current_Date"
|
||
Add-Content -Path $OutputFile -Value "..."
|