Housekeeping abandoned
GPOs or Group Policy
Objects can be unwieldy at the best of times. I walked into an organisation and
was landed in the middle of a quagmire of chaos with over a thousand GPOs, some
first created over 16 years ago.
There is no guessing that
basic housekeeping was the furthest from the mind of the administrators of that
estate, an Aegean stable of egregious compromise and mismanagement awaits, but
what to do?
Get an understanding
of what has been done, and work to give a form of sanity to the infrastructure with
the view to an eventual cleanup and the preparation of ingesting the best parts
of this setup into EntraID. It would seem like a pipedream.
Just the shock, I
decided to backup all the GPOs, which took just under 7 hours. Now that I had a
backup, it would be easier to search the GPReport.XML files in my backup folder
for historical information than to search the live environment.
ChatGPT does the
heavylifting
So, I offered
ChatGPT-4 an extensive prompt of requirements to read the files, find the
string, and output the result to a CSV file, but also just because the GPO might be
linked to several containers, Domain level or OUs, there is a separate output
file for if the GPO is linked.
I guess, manipulating
an XML file can be fun to extract the information you need, but this is not
about XML gymnastics, just getting useful information out of GPOs.
The Code:
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 | <# ==================================================================================== Created with: ChatGPT-4 and PowerShell ISE Created on: 03/05/2024 00:46 AM Curated by: Akin Akintayo Filename: Search-StringInGPOXML.ps1 ------------------------------------------------------------------------------------ Purpose: This is created as a time-saving script to search through backed-up GPOs in a folder specified for a string and output first to a CSV file, all occurrences of the string and in a separate LinksTo file list all the links to the GPO ==================================================================================== #> # Define the path to the directory containing GPO backups $BackupDirectory = "C:\Repository\GPO\GPOBackup\Backup-02-05-2024" # Define the output path for the CSV file $OutputPath = "C:\Repository\GPO\GPResults" # Prompt for the search string $searchString = Read-Host "Please enter the string to search for" # Create a filename for the CSV based on the current date and the search string $UniqueFile = "$(Get-Date -Format 'yy-MMM-dd-HH-mm-ss')-$($searchString -replace ' ', '')" $csvFileName = "$($UniqueFile)-GPOReport.csv" $csvFileFullPath = Join-Path $OutputPath $csvFileName $LinkInfoFilename = "$($UniqueFile)-LinksTo.Log" $LinksToFullPath = Join-Path $OutputPath $LinkInfoFilename # Import the GroupPolicy module Import-Module GroupPolicy # Get all GPReport.xml files from the specified directory $xmlFiles = Get-ChildItem -Path $BackupDirectory -Filter "GPReport.xml" -Recurse -Depth 1 # Prepare an array to hold the results $results = @() # Loop through each XML file to search for the specified string foreach ($file in $xmlFiles) { # Load the XML content [xml]$xmlContent = Get-Content -Path $file.FullName # Check if the XML content contains the search string if ($xmlContent.OuterXml.Contains($searchString)) { # Extract GPO details # $gpoDetails = Get-GPO -Guid $xmlContent.GPO.Identifier -All # Create a custom object to hold the necessary details $result = [PSCustomObject]@{ Name = $xmlContent.GPO.Name GUID = $xmlContent.GPO.Identifier.Identifier.'#text' Linked = $xmlContent.GPO.LinksTo.Enabled GPOFolder = $file.Directory.Name } If ($xmlContent.GPO.LinksTo.Enabled) { "$($xmlContent.GPO.Name) `n`n $($xmlContent.GPO.LinksTo.SOMPath)`n`n`n`n" | Out-File -FilePath $LinksToFullPath -Append -Width 200 } # Add the custom object to the results array $results += $result } } # Export the results to a CSV file $results | Export-Csv -Path $csvFileFullPath -NoTypeInformation # Output the name of the CSV file created Write-Host "CSV file created: $csvFileFullPath" |
No comments:
Post a Comment