Ever wondered why your Active Directory monitoring shows computer account creation and deletion events perfectly, but Organizational Unit (OU) operations seem to disappear into thin air?
This comprehensive technical walkthrough will show you exactly why Event IDs 5137 (OU creation) and 5141 (OU deletion) go missing, how to diagnose the root cause using built-in Windows tools, and most importantly - let’s get started.
The Problem: Missing OU Operation Events
You've enabled Active Directory auditing, configured your audit policies correctly, and set up monitoring scripts - but you're still not seeing the events you expect. Specifically, you're missing:
- Event ID 5137 - Directory service object was created (OU creation)
- Event ID 5141 - Directory service object was deleted (OU deletion)
- Event ID 5139 - Directory service object was moved (OU moved)
Meanwhile, other AD events like computer account creation (4741) and deletion (4743) are working perfectly. What's going on?
Step 1 : Understanding the Two-Layer Auditing System
Active Directory auditing requires two separate configurations to work properly:
Layer 1: Audit Policy (The "Should We Log?" Setting)
This is the domain-wide policy that tells Windows whether to generate audit events for directory services.
Layer 2: Audit ACL (The "What Should We Log?" Setting)
The audit ACL on specific AD objects defines which operations on those objects should actually generate audit events.
The key insight: You can have Layer 1 enabled but still get no events if Layer 2 isn't configured correctly.
Step 2: Verify Your Audit Policy is Enabled
First, confirm that your audit policies are actually enabled:
# Check current audit policy settings
auditpol /get /subcategory:"Directory Service Changes"
auditpol /get /subcategory:"Directory Service Access"
You should see:
Directory Service Changes Success and Failure
Directory Service Access Success and Failure
If these aren't enabled, fix them:
auditpol /set /subcategory:"Directory Service Changes" /success:enable /failure:enable
auditpol /set /subcategory:"Directory Service Access" /success:enable /failure:enable
Step 3: Enable Audit Logging to Capture Events
⚠️ Important: Test this in a lab environment first! Domain-level AD Audit logging can have security implications.
First we need to start adsiedit.msc from the Run box:
Next we need to connect to the default naming context as below:
Then from the Security options click Advanced:
Then we need the Auditing tab, we do not want the change security settings, that would be bad, when on the Auditing tab click Add:
We now need to add certain groups to the Audit permissions, you cannot add Everyone that would be to much logging so we need to add the privileged groups, let work though Domain Admins but remember you have to repeat this on all the other groups (shown below as Entry 1-3)
Domain Admins should look like this:
Note : The Domains Admins here also has the Modify Owner and and Modify Permissions (to track other updates as well, this is not required)
Entry 1: Enterprise Admins
- Principal: BEAR\Enterprise Admins
- Type: Success/Failure
- Permissions: Create all child objects, Delete all child objects, Delete, Delete subtree, Write all properties
Entry 2: Account Operators
- Principal: BEAR\Account Operators
- Type: Success/Failure
- Permissions: Create all child objects, Delete all child objects, Delete, Delete subtree, Write all properties
Entry 3: Administrators (Domain Local Admin)
- Principal: BEAR\Administrators
- Type: Success/Failure
- Permissions: Create all child objects, Delete all child objects, Delete, Delete subtree, Write all properties
When you click OK you will notice this is blank as we have not created any objects yet, if you did create objects before this would still be blank as the audit was not enabled:
Now lets start Active Users and Computers (using dsa.msc) and lets create an OU, delete an OU and move an OU, we should then see the correct event appear in the eventlog, this has been created:
Let us move "FrostedHoney" into "ClearHoney" and that will confirm that the "OU move" has been logged as well:
This is then confirmed in the event log as well as you can see here:
If we then look at the full event log entry we can see that we are now tracking the OU and the user that performed it:
A directory service object was moved.
Subject:
Security ID: BEAR\mooney
Account Name: mooney
Account Domain: BEAR
Logon ID: 0x83E97
Directory Service:
Name: bear.local
Type: Active Directory Domain Services
Object:
Old DN: OU=FrostyHoney,OU=HoneyGroups,DC=bear,DC=local
New DN: OU=FrostyHoney,OU=ClearHoney,OU=HoneyGroups,DC=bear,DC=local
GUID: OU=FrostyHoney,OU=HoneyGroups,DC=bear,DC=local
Class: organizationalUnit
Operation:
Correlation ID: {10c8b135-2872-42b5-8c0f-27d9baadab87}
Application Correlation ID: -Step 4 : Events You Should Now See
After the fix, your monitoring should capture:
- 5137 - Directory service object was created (OU creation)
- 5141 - Directory service object was deleted (OU deletion)
- 5136 - Directory service object was modified (OU moves/modifications)
Troubleshooting Tips
If you're still not seeing events after the fix:
- Check audit policy inheritance - Ensure settings apply to child OUs
- Verify domain controller event forwarding - Events might be generated but not forwarded
- Review timing - Some events may have delays
- Test with different accounts - Ensure the test account has OU creation permissions
- Check Event Log size limits - Logs might be rolling over too quickly
Get-WinEvent -ComputerName beardc1.bear.local -FilterHashtable @{LogName='Security'; ID=5141} |
ForEach-Object {
$Event = [xml]$_.ToXml()
[PSCustomObject]@{
TimeCreated = $_.TimeCreated
ObjectDN = $Event.Event.EventData.Data[8].'#text' # Object DN
ObjectClass = $Event.Event.EventData.Data[9].'#text' # Object Class
SubjectUserName = $Event.Event.EventData.Data[1].'#text' # Who deleted it
SubjectDomainName = $Event.Event.EventData.Data[2].'#text'
}
} | Format-Table -AutoSize
Get-WinEvent -ComputerName beardc1.bear.local -FilterHashtable @{LogName='Security'; ID=4743} |
ForEach-Object {
$Event = [xml]$_.ToXml()
[PSCustomObject]@{
TimeCreated = $_.TimeCreated
ObjectDN = $Event.Event.EventData.Data[0].'#text' # Target computer account
SubjectUserName = $Event.Event.EventData.Data[4].'#text' # Who deleted it
SubjectDomainName = $Event.Event.EventData.Data[5].'#text'
SubjectLogonId = $Event.Event.EventData.Data[6].'#text'
}
} | Format-Table -AutoSize
# Legacy events (Windows 2003/2008 style)
Get-WinEvent -ComputerName beardc1 -FilterHashtable @{
LogName='Security'
ID=@(630, 631, 632, 633, 634, 635, 636, 637, 4741, 4742, 4743)
StartTime=(Get-Date).AddHours(-24)
} | ForEach-Object {
$Event = [xml]$_.ToXml()
$eventData = @{}
foreach ($data in $Event.Event.EventData.Data) {
if ($data.Name) {
$eventData[$data.Name] = $data.'#text'
}
}
[PSCustomObject]@{
TimeCreated = $_.TimeCreated
EventID = $_.Id
EventDescription = switch ($_.Id) {
630 { "Computer Account Created" }
631 { "Computer Account Deleted" }
632 { "Computer Account Enabled" }
633 { "Computer Account Disabled" }
634 { "Computer Account Changed" }
635 { "Computer Group Created" }
636 { "Computer Group Changed" }
637 { "Computer Group Deleted" }
4741 { "Computer Account Created" }
4742 { "Computer Account Changed" }
4743 { "Computer Account Deleted" }
default { "Unknown Computer Event" }
}
TargetAccount = if ($eventData.TargetUserName) { $eventData.TargetUserName } else { $eventData.SamAccountName }
ChangedBy = if ($eventData.SubjectUserName) { "$($eventData.SubjectDomainName)\$($eventData.SubjectUserName)" } else { "Unknown" }
TargetDomain = $eventData.TargetDomainName
}
} | Format-Table -AutoSize
# Search for OU creation and deletion events (modern + legacy)
Get-WinEvent -ComputerName beardc1 -FilterHashtable @{
LogName='Security'
ID=@(5137, 5141, 630, 631, 632, 633, 634, 635, 636, 637) # Modern + Legacy OU events
StartTime=(Get-Date).AddHours(-24)
} | ForEach-Object {
$Event = [xml]$_.ToXml()
$eventData = @{}
# Parse all event data into a hashtable
foreach ($data in $Event.Event.EventData.Data) {
if ($data.Name) {
$eventData[$data.Name] = $data.'#text'
}
}
[PSCustomObject]@{
TimeCreated = $_.TimeCreated
EventID = $_.Id
EventDescription = switch ($_.Id) {
5137 { "Directory Object Created" }
5141 { "Directory Object Deleted" }
630 { "User Account Created" }
631 { "User Account Deleted" }
632 { "User Account Enabled" }
633 { "User Account Disabled" }
634 { "User Account Changed" }
635 { "Security Group Created" }
636 { "Security Group Changed" }
637 { "Security Group Deleted" }
default { "Unknown Event" }
}
ObjectDN = $eventData.ObjectDN
ObjectClass = $eventData.ObjectClass
ObjectName = if ($eventData.ObjectDN) {
($eventData.ObjectDN -split ',')[0] -replace '^.+=',''
} else {
$eventData.TargetUserName
}
ChangedBy = if ($eventData.SubjectUserName) {
"$($eventData.SubjectDomainName)\$($eventData.SubjectUserName)"
} else {
"Unknown"
}
TargetDomain = $eventData.TargetDomainName
}
} | Where-Object {
$_.ObjectClass -eq "organizationalUnit" -or
$_.ObjectDN -like "*OU=*" -or
$_.EventDescription -like "*Group*"
} | Sort-Object TimeCreated -Descending | Format-Table -AutoSize
# Check for ANY 5137/5141 events in the last 24 hours (not just OU)
Get-WinEvent -ComputerName beardc1 -FilterHashtable @{
LogName='Security'
ID=@(5137, 5141)
StartTime=(Get-Date).AddHours(-24)
} | Select-Object TimeCreated, Id, @{
Name='ObjectInfo'
Expression={
$xml = [xml]$_.ToXml()
$eventData = @{}
foreach ($data in $xml.Event.EventData.Data) {
if ($data.Name) { $eventData[$data.Name] = $data.'#text' }
}
"Class: $($eventData.ObjectClass) | DN: $($eventData.ObjectDN)"
}
} | Format-Table -AutoSize
# Search for legacy OU events - these are the most likely candidates
Get-WinEvent -ComputerName beardc1 -FilterHashtable @{
LogName='Security'
ID=@(635, 637, 656, 658, 660, 662, 642, 643) # Legacy group/container events
StartTime=(Get-Date).AddHours(-24)
} | ForEach-Object {
$Event = [xml]$_.ToXml()
[PSCustomObject]@{
TimeCreated = $_.TimeCreated
EventID = $_.Id
EventDescription = switch ($_.Id) {
635 { "Security Group Created" }
637 { "Security Group Deleted" }
642 { "User Account Changed" }
643 { "Domain Policy Changed" }
656 { "A member was added to a security-enabled group" }
658 { "A member was removed from a security-enabled group" }
660 { "Group type changed" }
662 { "A member was removed from a security-disabled group" }
default { "Legacy Event $($_.Id)" }
}
Message = $_.Message.Substring(0, [Math]::Min(100, $_.Message.Length))
}
} | Format-Table -Wrap
Remember: Always test in a lab environment first, and document your changes for future reference. AD auditing issues can be subtle, but following this systematic approach will help you identify and fix the root cause..