Jorge's Quest For Knowledge!

All You Need To Know About Identity And Security On-Premises And In The Cloud. It's Just Like An Addiction, The More You Have, The More You Want To Have!

Archive for the ‘Conflicting Objects’ Category

(2014-09-17) Finding Conflicting Objects In Your AD

Posted by Jorge on 2014-09-17


You might have seen it in your own AD or in somebody else’s AD, conflicting/duplicate objects. Those objects are exactly same objects that were created on different RWDCs at nearly the same time. After replication kicks and those conflicting/duplicate objects replicate to other RWDCs, AD replication needs to apply its own conflict resolution mechanism to ensure every object is and remains unique.

So, let’s say you create the object "CN=TestObject,OU=MyOU,DC=DOMAIN,DC=COM" on 2 different RWDCs at (nearly) the same time. After AD replication has converged you will see the following objects:

  1. "CN=TestObjectACNF:4862d44c-76ab-41b7-bac8-8682900e661b,OU=MyOU,DC=DOMAIN,DC=COM"
  2. "CN=TestObject,OU=MyOU,DC=DOMAIN,DC=COM"

[1] is the first created object and [2] was the last created object. The last object created is always the one that does not have ACNF:<objectGUID> in its CN/RDN. AD puts ACNF:<objectGUID> in the CN/RDN telling us it is a CONflict object and making sure it is unique in the container where also the other object is in.

The following PowerShell script helps you finding these objects in your AD forest. Based upon the information of the objects you need to determine yourself which of the two objects should be removed and which one can remain in AD.

# Clear The Screen Clear-Host # Checking Number Of Arguments $numArgs = $args.count $arg0 = $args[0] # Discovering A GC Retrieving Its DNS HostName $dnsHostNameGC = (Get-ADDomainController -Service GlobalCatalog -Discover:$true).HostName[0] $gcHostPort = $dnsHostNameGC + ":3268" $dsContextDC = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("DirectoryServer",$dnsHostNameGC) $dc = [System.DirectoryServices.ActiveDirectory.DomainController]::GetDomainController($dsContextDC) # General Execution Of Script If ($numArgs -eq 0) { $listOfConflictingObjects = Get-ADObject -server $gcHostPort -LDAPFilter '(name=*CNF:*)' } If ($numArgs -eq 1) { If ($arg0.ToLower() -eq "computer") { $listOfConflictingObjects = Get-ADComputer -server $gcHostPort -LDAPFilter '(name=*CNF:*)' -Properties pwdLastSet } If ($arg0.ToLower() -eq "user") { $listOfConflictingObjects = Get-ADUser -server $gcHostPort -LDAPFilter '(name=*CNF:*)' -Properties pwdLastSet } } If ($listOfConflictingObjects -ne $null) { $listOfDuplicates = @() $listOfConflictingObjects | %{ $objCNF = $_ $dnCNFobj = $objCNF.DistinguishedName $classCNFobj = $_.ObjectClass $guidCNFobj = $_.ObjectGUID If ($numArgs -eq 1 -And ($arg0.ToLower() -eq "computer" -Or $arg0.ToLower() -eq "user")) { $sAMAccountCNFobj = $_.SamAccountName $pwdLastSetCNFobj = $_.pwdLastSet If ($pwdLastSetCNFobj -ne $null){ $pwdLastSetCNFobj = Get-Date -Date ([DateTime]::FromFileTime([Int64]::Parse($pwdLastSetCNFobj))) -Format "yyyy-MM-dd HH:mm:ss" } Else { $pwdLastSetCNFobj = "---" } } $objCNFMetadata = $dc.GetReplicationMetadata($dnCNFobj) $objCNFOrigSrv = $objCNFMetadata | %{($_.objectclass).OriginatingServer} $objCNFOrigTime = $objCNFMetadata | %{($_.objectclass).LastOriginatingChangeTime} $dnORGobj = $dnCNFobj.Substring(0,$dnCNFobj.IndexOf("\")) + $dnCNFobj.Substring($dnCNFobj.IndexOf(",")) If ($numArgs -eq 0) { $objORG = Get-ADObject -server $gcHostPort -Identity $dnORGobj } If ($numArgs -eq 1) { If ($arg0.ToLower() -eq "computer") { $objORG = Get-ADComputer -server $gcHostPort -Identity $dnORGobj -Properties pwdLastSet } If ($arg0.ToLower() -eq "user") { $objORG = Get-ADUser -server $gcHostPort -Identity $dnORGobj -Properties pwdLastSet } } $dnORGobj = $null $classORGobj = $null $guidORGobj = $null $sAMAccountORGobj = $null $pwdLastSetORGobj = $null $objORGMetadata = $null If ($objORG -ne $null) { $dnORGobj = $objORG.DistinguishedName $classORGobj = $objORG.ObjectClass $guidORGobj = $objORG.ObjectGUID If ($numArgs -eq 1 -And ($arg0.ToLower() -eq "computer" -Or $arg0.ToLower() -eq "user")) { $sAMAccountORGobj = $objORG.SamAccountName $pwdLastSetORGobj = $objORG.pwdLastSet If ($pwdLastSetORGobj -ne $null){ $pwdLastSetORGobj = Get-Date -Date ([DateTime]::FromFileTime([Int64]::Parse($pwdLastSetORGobj))) -Format "yyyy-MM-dd HH:mm:ss" } Else { $pwdLastSetORGobj = "---" } } $objORGMetadata = $dc.GetReplicationMetadata($dnORGobj) $objORGOrigSrv = $objORGMetadata | %{($_.objectclass).OriginatingServer} $objORGOrigTime = $objORGMetadata | %{($_.objectclass).LastOriginatingChangeTime} } Else { $dnORGobj = "Does Not Exit" $classORGobj = "Does Not Exit" $guidORGobj = "Does Not Exit" If ($numArgs -eq 1 -And ($arg0.ToLower() -eq "computer" -Or $arg0.ToLower() -eq "user")) { $sAMAccountORGobj = "Does Not Exit" $pwdLastSetORGobj = "Does Not Exit" } $objORGOrigSrv = "Does Not Exit" $objORGOrigTime = "Does Not Exit" } If ($numArgs -eq 0) { $adObj = "" | Select "> > >DN (CNF)..........","objectClass (CNF)......","objectGUID (CNF).......","Originating DC (CNF)...","Originating Time (CNF).","> > >DN (ORG)..........","objectClass (ORG)......","objectGUID (ORG).......","Originating DC (ORG)...","Originating Time (ORG)." } If ($numArgs -eq 1 -And ($arg0.ToLower() -eq "computer" -Or $arg0.ToLower() -eq "user")) { $adObj = "" | Select "> > >DN (CNF)..........","objectClass (CNF)......","objectGUID (CNF).......","Account Name (CNF).....","PWD Last Set (CNF).....","Originating DC (CNF)...","Originating Time (CNF).","> > >DN (ORG)..........","objectClass (ORG)......","objectGUID (ORG).......","Account Name (ORG).....","PWD Last Set (ORG).....","Originating DC (ORG)...","Originating Time (ORG)." } $adObj."> > >DN (CNF).........." = $dnCNFobj $adObj."objectClass (CNF)......" = $classCNFobj $adObj."objectGUID (CNF)......." = $guidCNFobj If ($numArgs -eq 1 -And ($arg0.ToLower() -eq "computer" -Or $arg0.ToLower() -eq "user")) { $adObj."Account Name (CNF)....." = $sAMAccountCNFobj $adObj."PWD Last Set (CNF)....." = $pwdLastSetCNFobj } $adObj."Originating DC (CNF)..." = $objCNFOrigSrv $adObj."Originating Time (CNF)." = $objCNFOrigTime $adObj."> > >DN (ORG).........." = $dnORGobj $adObj."objectClass (ORG)......" = $classORGobj $adObj."objectGUID (ORG)......." = $guidORGobj If ($numArgs -eq 1 -And ($arg0.ToLower() -eq "computer" -Or $arg0.ToLower() -eq "user")) { $adObj."Account Name (ORG)....." = $sAMAccountORGobj $adObj."PWD Last Set (ORG)....." = $pwdLastSetORGobj } $adObj."Originating DC (ORG)..." = $objORGOrigSrv $adObj."Originating Time (ORG)." = $objORGOrigTime $listOfDuplicates += $adObj } Write-Host "" If ($numArgs -eq 0) { Write-Host "LIST OF DUPLICATE/CONFLICTING OBJECTS IN THE AD FOREST" -Foregroundcolor Cyan } If ($numArgs -eq 1 -And $arg0.ToLower() -eq "computer") { Write-Host "LIST OF DUPLICATE/CONFLICTING COMPUTER OBJECTS IN THE AD FOREST" -Foregroundcolor Cyan } If ($numArgs -eq 1 -And $arg0.ToLower() -eq "user") { Write-Host "LIST OF DUPLICATE/CONFLICTING USER OBJECTS IN THE AD FOREST" -Foregroundcolor Cyan } $listOfDuplicates | FL } Else { Write-Host "NO DUPLICATE/CONFLICTING OBJECTS DETECTED IN THE AD FOREST" -Foregroundcolor Green }

The following is an example result when executing the script as: .\Retrieve-List-Of-Conflicting-Objects.ps1

image

Figure 1: Detecting Conflicting/Duplicate Objects In The AD Forest

The following is an example result when executing the script as: .\Retrieve-List-Of-Conflicting-Objects.ps1 computer

image

Figure 2: Detecting Conflicting/Duplicate Computer Objects In The AD Forest

The following is an example result when executing the script as: .\Retrieve-List-Of-Conflicting-Objects.ps1 user

image

Figure 3: Detecting Conflicting/Duplicate User Objects In The AD Forest

Get the PowerShell code from HERE.

Cheers,

Jorge

———————————————————————————————

* This posting is provided "AS IS" with no warranties and confers no rights!

* Always evaluate/test yourself before using/implementing this!

* DISCLAIMER:

https://jorgequestforknowledge.wordpress.com/disclaimer/

———————————————————————————————

############### Jorge’s Quest For Knowledge #############

#########

http://JorgeQuestForKnowledge.wordpress.com/ ########

———————————————————————————————

Posted in Active Directory Domain Services (ADDS), Conflicting Objects, PowerShell, Tooling/Scripting | 4 Comments »

 
%d bloggers like this: