I was thinking about the audit log on the domain controllers that logs all operations by users in the Security log if you have it enabled, which really in this day and age you should have this enabled as monitoring and alerting is required to ensure integrity and consistency.
This report will pull all the security logs with the defined UPN listed in the script, so if you are making lots of changes this may take some time, however I had excluded Event ID 4663/4662 from this script for "object access" as this can be a very noisy event that is not very helpful for detecting modifications.
This script will get both the UPN and the SamAccountName so you can use the UPN in the script, which is magical, this is the script:
Note : if you open the file in Excel, you will get a summary of the high-level activity, If you open this as a CSV file and say Notepad++ you will see all the additional details
# Define the user accounts to search for
$users = @("naughty.bear.a@bear.local", "suspicious.bear.b@bear.local")
# Function to get SAM account names from UPNs
function Get-SamAccountNames {
param (
[array]$upns
)
$samAccounts = @()
foreach ($upn in $upns) {
$samAccount = Get-ADUser -Filter {UserPrincipalName -eq $upn} | Select-Object -ExpandProperty SamAccountName
if ($samAccount) {
$samAccounts += $samAccount
}
}
return $samAccounts
}
# Get the SAM account names for the provided UPNs
$samAccounts = Get-SamAccountNames -upns $users
# Combine UPNs and SAM account names into a single array
$searchAccounts = $users + $samAccounts
# Get the list of all domain controllers
$domainControllers = Get-ADDomainController -Filter *
# Function to search event logs on a specific domain controller
function Search-UserEvents {
param (
[string]$domainController,
[array]$accounts
)
Write-Output "Searching $domainController for all relevant events related to specified user accounts..."
# Create an empty array to store results
$results = @()
foreach ($account in $accounts) {
# Update XPath query to exclude Event IDs 4662 and 4663
$query = "*[System[(EventID!=4662) and (EventID!=4663)] and EventData[Data and (Data='$account')]]"
# Search the security event log for any events related to the user accounts
$events = Get-WinEvent -ComputerName $domainController -LogName Security -FilterXPath $query -ErrorAction SilentlyContinue
# If events are found, output the relevant details
if ($events) {
foreach ($event in $events) {
$eventDetails = @{
TimeCreated = $event.TimeCreated
DomainController = $domainController
EventID = $event.Id
UserAccount = $account
EventMessage = $event.Message
}
$results += [PSCustomObject]$eventDetails
}
} else {
Write-Output "No relevant events found for $account on $domainController."
}
}
return $results
}
# Initialize a collection for all results
$allResults = @()
# Iterate through each domain controller and search for events
foreach ($dc in $domainControllers) {
Write-Output "---------------------------------------"
Write-Output "Now searching on Domain Controller: $($dc.HostName)"
Write-Output "---------------------------------------"
$allResults += Search-UserEvents -domainController $dc.HostName -accounts $searchAccounts
}
# Export results to CSV
if ($allResults) {
$allResults | Select-Object TimeCreated, DomainController, EventID, UserAccount, EventMessage | Export-Csv -Path "UserEvents.csv" -NoTypeInformation
Write-Output "Results have been exported to UserEvents.csv"
} else {
Write-Output "No events found."
}