Last active
October 21, 2025 19:04
-
-
Save zjorz/6a565db8d49e43b86fc965fc08331e24 to your computer and use it in GitHub Desktop.
Code to sync password from DSRM Placeholder Account in AD to the local DSRM Admin Account on DCs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # SOURCE: https://gist.github.com/zjorz/6a565db8d49e43b86fc965fc08331e24/ | |
| Invoke-Command -ScriptBlock { | |
| Clear-Host | |
| $scriptMode = "ADSIorSDSP" # "ADSIorSDSP" Or "ADPoSH" | |
| Write-Host "" | |
| Write-Host "###############################################################################" -Foregroundcolor Yellow | |
| Write-Host "### SYNCHING PASSWORD FROM DSRM PLACEHOLDER ACCOUNT IN AD FOR DCs ###" -Foregroundcolor Yellow | |
| Write-Host "###############################################################################" -Foregroundcolor Yellow | |
| Write-Host "" | |
| $currentScriptFilePath = $MyInvocation.MyCommand.Definition | |
| $currentScriptFolderPath = Split-Path $currentScriptFilePath | |
| $controlAttribute = "extensionAttribute1" | |
| $controlValue = "RESET" | |
| $resetAcknowledgementAttribute = "info" # For The DC Computer Account - Attribute Is Part Of Personal Information Attribute Set To Also Support RODCs With The Default Permissions Configured | |
| $dateTime = Get-Date -Format "yyyy-MM-dd HH:mm:ss" | |
| $localComputerName = $(Get-CimInstance -Class Win32_ComputerSystem).Name | |
| $computerADDomainName = $(Get-CimInstance -Class Win32_ComputerSystem).Domain | |
| $fqdnLocalComputerDomain = $localComputerName + "." + $computerADDomainName | |
| $fqdnLocalComputerDNS = [System.Net.Dns]::GetHostByName($localComputerName).HostName | |
| $adRootDse = [ADSI]"LDAP://$fqdnLocalComputerDNS/RootDSE" | |
| $configNCDN = $adRootDse.Properties.configurationNamingContext[0] | |
| If ($scriptMode -eq "ADSIorSDSP") { | |
| $adDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetComputerDomain() | |
| $adDomainDN = $adDomain.GetDirectoryEntry().Properties["DistinguishedName"].Value | |
| } | |
| If ($scriptMode -eq "ADPoSH") { | |
| Import-Module ActiveDirectory | |
| $adDomain = Get-ADdomain -Current LocalComputer | |
| $adDomainDN = $adDomain.DistinguishedName | |
| } | |
| If ($scriptMode -eq "ADSIorSDSP") { | |
| $adsiSearcher = New-Object DirectoryServices.DirectorySearcher | |
| $adsiSearcher.SearchRoot = [ADSI]"LDAP://$fqdnLocalComputerDNS/OU=Domain Controllers,$adDomainDN" | |
| $adsiSearcher.Filter = "(dNSHostName=$fqdnLocalComputerDNS)" | |
| $adsiSearcher.PropertiesToLoad.Add("msDS-isRODC") > $null | |
| $dcComputerAccountObject = $adsiSearcher.FindOne() | |
| If ($dcComputerAccountObject.Properties."msds-isrodc"[0] -eq $false) { | |
| $dcType = "RWDC" | |
| } Else { | |
| $dcType = "RODC" | |
| } | |
| } | |
| If ($scriptMode -eq "ADPoSH") { | |
| If ((Get-ADDomainController -Identity $fqdnLocalComputerDNS -Server $fqdnLocalComputerDNS).IsReadOnly -eq $false) { | |
| $dcType = "RWDC" | |
| } Else { | |
| $dcType = "RODC" | |
| } | |
| } | |
| $sAMAccountName = "dsrm.$dcType`s" | |
| # DSRM Placeholder Account | |
| $dsrmAdmAccountObject = $null | |
| $dsrmAdmAccountDN = $null | |
| $controlAttributeValue = $null | |
| If ($scriptMode -eq "ADSIorSDSP") { | |
| $adsiSearcher = New-Object DirectoryServices.DirectorySearcher | |
| $adsiSearcher.SearchRoot = [ADSI]"LDAP://$fqdnLocalComputerDNS/$adDomainDN" | |
| $adsiSearcher.Filter = "(sAMAccountName=$sAMAccountName)" | |
| $dsrmAdmAccountObject = $adsiSearcher.FindOne() | |
| If (-not [string]::IsNullOrEmpty($dsrmAdmAccountObject)) { | |
| $dsrmAdmAccountDN = $dsrmAdmAccountObject.Properties.distinguishedname[0] | |
| If (-not [string]::IsNullOrEmpty($dsrmAdmAccountObject.Properties.$($controlAttribute.ToLower()))) { | |
| $controlAttributeValue = $dsrmAdmAccountObject.Properties.$($controlAttribute.ToLower())[0] | |
| } Else { | |
| $controlAttributeValue = "_EMPTY_" | |
| } | |
| } Else { | |
| $dsrmAdmAccountDN = "_UNKNOWN_" | |
| $controlAttributeValue = "_UNKNOWN_" | |
| } | |
| } | |
| If ($scriptMode -eq "ADPoSH") { | |
| $dsrmAdmAccountObject = Get-ADUser -SearchBase $adDomainDN -LDAPFilter "(sAMAccountName=$sAMAccountName)" -Properties $controlAttribute -Server $fqdnLocalComputerDNS | |
| If (-not [string]::IsNullOrEmpty($dsrmAdmAccountObject)) { | |
| $dsrmAdmAccountDN = $dsrmAdmAccountObject.DistinguishedName | |
| If (-not [string]::IsNullOrEmpty($dsrmAdmAccountObject.$controlAttribute)) { | |
| $controlAttributeValue = $dsrmAdmAccountObject.$controlAttribute | |
| } Else { | |
| $controlAttributeValue = "_EMPTY_" | |
| } | |
| } Else { | |
| $dsrmAdmAccountDN = "_UNKNOWN_" | |
| $controlAttributeValue = "_UNKNOWN_" | |
| } | |
| } | |
| Write-Host " > Current Script Path...: $currentScriptFilePath" -Foregroundcolor Yellow | |
| Write-Host " > Current Folder Path...: $currentScriptFolderPath" -Foregroundcolor Yellow | |
| Write-Host " > Script Mode...........: $scriptMode" -Foregroundcolor Yellow | |
| Write-Host " > Control Attribute.....: '$controlAttribute' (On DSRM Placeholder User Account!)" -Foregroundcolor Yellow | |
| Write-Host " > Control Value.........: '$controlValue'" -Foregroundcolor Yellow | |
| Write-Host " > Reset Ack Attribute...: '$resetAcknowledgementAttribute' (On DC Computer Account!)" -Foregroundcolor Yellow | |
| Write-Host " > Date/Time.............: $dateTime" -Foregroundcolor Yellow | |
| Write-Host " > FQDN In AD Domain.....: $fqdnLocalComputerDomain" -Foregroundcolor Yellow | |
| Write-Host " > FQDN In DNS...........: $fqdnLocalComputerDNS" -Foregroundcolor Yellow | |
| Write-Host " > DC Type...............: $dcType" -Foregroundcolor Yellow | |
| Write-Host " > DSRM sAMAccountName...: $sAMAccountName" -Foregroundcolor Yellow | |
| Write-Host " > DSRM DistinguishedName: $dsrmAdmAccountDN" -Foregroundcolor Yellow | |
| Write-Host "" | |
| "Starting DSRM Account Sync | $fqdnLocalComputerDNS | $dateTime" | Out-File $(Join-Path $currentScriptFolderPath "NTDSUTIL-SYNC-DSRM-PWD-ON-$dcType`s-FROM-DOMAIN-ACCOUNT-$fqdnLocalComputerDNS.LOG") -Append | |
| If (-not [string]::IsNullOrEmpty($dsrmAdmAccountObject) -And $controlAttributeValue -eq $controlValue) { | |
| If ($dcType -eq "RWDC") { | |
| $targetedRWDCContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("DirectoryServer", $fqdnLocalComputerDNS) | |
| $targetedRWDCObject = [System.DirectoryServices.ActiveDirectory.DomainController]::GetDomainController($targetedRWDCContext) | |
| $objectMetadataOnRWDC = $targetedRWDCObject.GetReplicationMetadata($dsrmAdmAccountDN) | |
| $orgDateTimeOnRWDC = $(Get-Date (Get-Date $objectMetadataOnRWDC.unicodepwd.LastOriginatingChangeTime).ToUniversalTime() -Format "yyyy-MM-ddTHH:mm:ss") | |
| $versionOnRWDC = $objectMetadataOnRWDC.unicodepwd.Version | |
| } | |
| If ($dcType -eq "RODC") { | |
| $sitesDN = "CN=Sites,$configNCDN" | |
| If ($scriptMode -eq "ADSIorSDSP") { | |
| $adsiSearcher = New-Object DirectoryServices.DirectorySearcher | |
| $adsiSearcher.SearchRoot = [ADSI]"LDAP://$fqdnLocalComputerDNS/$sitesDN" | |
| $adsiSearcher.Filter = "(&(objectClass=server)(dNSHostName=$fqdnLocalComputerDNS))" | |
| $rodcServerObject = $adsiSearcher.FindOne() | |
| $rodcComputerAccountDN = $rodcServerObject.Properties.serverreference[0] | |
| $rodcNTDSSettingsObjectDN = "CN=NTDS Settings,$($rodcServerObject.Properties.distinguishedname[0])" | |
| $adsiSearcher = New-Object DirectoryServices.DirectorySearcher | |
| $adsiSearcher.SearchRoot = [ADSI]"LDAP://$fqdnLocalComputerDNS/$rodcNTDSSettingsObjectDN" | |
| $adsiSearcher.Filter = "(&(objectClass=nTDSConnection)(name=RODC Connection (SYSVOL)))" | |
| $rodcSYSVOLConnObj = $adsiSearcher.FindOne() | |
| $sourceRWDCNTDSSettingsObjectDN = $rodcSYSVOLConnObj.Properties.fromserver[0] | |
| $sourceRWDCServerObjectDN = $sourceRWDCNTDSSettingsObjectDN.Replace("CN=NTDS Settings,","") | |
| $adsiSearcher = New-Object DirectoryServices.DirectorySearcher | |
| $adsiSearcher.SearchRoot = [ADSI]"LDAP://$fqdnLocalComputerDNS/$sourceRWDCServerObjectDN" | |
| $sourceRWDCServerObject = $adsiSearcher.FindOne() | |
| $sourceRWDCFQDN = $sourceRWDCServerObject.Properties.dnshostname[0] | |
| } | |
| If ($scriptMode -eq "ADPoSH") { | |
| $rodcServerObject = Get-ADObject -SearchBase "CN=Sites,$configNCDN" -LDAPFilter "(&(objectClass=server)(dNSHostName=$fqdnLocalComputerDNS))" -Properties serverReference -Server $fqdnLocalComputerDNS | |
| $rodcComputerAccountDN = $rodcServerObject.serverReference | |
| $rodcNTDSSettingsObjectDN = "CN=NTDS Settings,$($rodcServerObject.DistinguishedName)" | |
| $rodcSYSVOLConnObj = Get-ADObject -SearchBase $rodcNTDSSettingsObjectDN -LDAPFilter "(&(objectClass=nTDSConnection)(name=RODC Connection (SYSVOL)))" -Properties fromServer -Server $fqdnLocalComputerDNS | |
| $sourceRWDCNTDSSettingsObjectDN = $rodcSYSVOLConnObj.fromServer | |
| $sourceRWDCServerObjectDN = $sourceRWDCNTDSSettingsObjectDN.Replace("CN=NTDS Settings,","") | |
| $sourceRWDCFQDN = (Get-ADObject -Identity $sourceRWDCServerObjectDN -Properties dNSHostName -Server $fqdnLocalComputerDNS).dNSHostName | |
| } | |
| $targetedRWDCContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("DirectoryServer", $sourceRWDCFQDN) | |
| $targetedRWDCObject = [System.DirectoryServices.ActiveDirectory.DomainController]::GetDomainController($targetedRWDCContext) | |
| $objectMetadataOnRWDC = $targetedRWDCObject.GetReplicationMetadata($dsrmAdmAccountDN) | |
| $orgDateTimeOnRWDC = $(Get-Date (Get-Date $objectMetadataOnRWDC.unicodepwd.LastOriginatingChangeTime).ToUniversalTime() -Format "yyyy-MM-ddTHH:mm:ss") | |
| $versionOnRWDC = $objectMetadataOnRWDC.unicodepwd.Version | |
| $adRootDse.Put("replicateSingleObject", $sourceRWDCNTDSSettingsObjectDN + ":" + $dsrmAdmAccountDN + ":SECRETS_ONLY") | |
| $adRootDse.SetInfo() | |
| $targetedRODCContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("DirectoryServer", $fqdnLocalComputerDNS) | |
| $targetedRODCObject = [System.DirectoryServices.ActiveDirectory.DomainController]::GetDomainController($targetedRODCContext) | |
| $objectMetadataOnRODC = $targetedRODCObject.GetReplicationMetadata($dsrmAdmAccountDN) | |
| $orgDateTimeOnRODC = $(Get-Date (Get-Date $objectMetadataOnRODC.unicodepwd.LastOriginatingChangeTime).ToUniversalTime() -Format "yyyy-MM-ddTHH:mm:ss") | |
| $versionOnRODC = $objectMetadataOnRODC.unicodepwd.Version | |
| Write-Host "Performing A Replicate Single Object For The Secrets Of '$sAMAccountName' To Make Sure The Latest Password Is In The Local RODC NTDS.DIT" -Foregroundcolor Yellow | |
| Write-Host "" | |
| Write-Host "Source RWDC FQDN.........................: $sourceRWDCFQDN" -Foregroundcolor Yellow | |
| Write-Host "Org Date/Time On RWDC....................: $orgDateTimeOnRWDC" -Foregroundcolor Yellow | |
| Write-Host "Version 'unicodePwd' Attribute On RWDC...: $versionOnRWDC" -Foregroundcolor Yellow | |
| Write-Host "Org Date/Time On RODC....................: $orgDateTimeOnRODC" -Foregroundcolor Yellow | |
| Write-Host "Version 'unicodePwd' Attribute On RODC...: $versionOnRODC" -Foregroundcolor Yellow | |
| Write-Host "" | |
| "Performing A Replicate Single Object For The Secrets Of '$sAMAccountName' To Make Sure The Latest Password Is In The Local RODC NTDS.DIT" | Out-File $(Join-Path $currentScriptFolderPath "NTDSUTIL-SYNC-DSRM-PWD-ON-$dcType`s-FROM-DOMAIN-ACCOUNT-$fqdnLocalComputerDNS.LOG") -Append | |
| "Source RWDC FQDN.........................: $sourceRWDCFQDN" | Out-File $(Join-Path $currentScriptFolderPath "NTDSUTIL-SYNC-DSRM-PWD-ON-$dcType`s-FROM-DOMAIN-ACCOUNT-$fqdnLocalComputerDNS.LOG") -Append | |
| "Org Date/Time On RWDC....................: $orgDateTimeOnRWDC" | Out-File $(Join-Path $currentScriptFolderPath "NTDSUTIL-SYNC-DSRM-PWD-ON-$dcType`s-FROM-DOMAIN-ACCOUNT-$fqdnLocalComputerDNS.LOG") -Append | |
| "Version 'unicodePwd' Attribute On RWDC...: $versionOnRWDC" | Out-File $(Join-Path $currentScriptFolderPath "NTDSUTIL-SYNC-DSRM-PWD-ON-$dcType`s-FROM-DOMAIN-ACCOUNT-$fqdnLocalComputerDNS.LOG") -Append | |
| "Org Date/Time On RODC....................: $orgDateTimeOnRODC" | Out-File $(Join-Path $currentScriptFolderPath "NTDSUTIL-SYNC-DSRM-PWD-ON-$dcType`s-FROM-DOMAIN-ACCOUNT-$fqdnLocalComputerDNS.LOG") -Append | |
| "Version 'unicodePwd' Attribute On RODC...: $versionOnRODC" | Out-File $(Join-Path $currentScriptFolderPath "NTDSUTIL-SYNC-DSRM-PWD-ON-$dcType`s-FROM-DOMAIN-ACCOUNT-$fqdnLocalComputerDNS.LOG") -Append | |
| } | |
| If (($dcType -eq "RODC" -And $versionOnRWDC -eq $versionOnRODC -And $orgDateTimeOnRWDC -eq $orgDateTimeOnRODC) -Or $dcType -eq "RWDC") { | |
| Write-Host "CONTINUING Local Password Reset For $localComputerName\Administrator From '$sAMAccountName'" -Foregroundcolor Yellow | |
| Write-Host "Execute Local Password Reset For $localComputerName\Administrator From '$sAMAccountName'" -Foregroundcolor Yellow | |
| Write-Host "" | |
| "CONTINUING - Local Password Reset For $localComputerName\Administrator From '$sAMAccountName'" | Out-File $(Join-Path $currentScriptFolderPath "NTDSUTIL-SYNC-DSRM-PWD-ON-$dcType`s-FROM-DOMAIN-ACCOUNT-$fqdnLocalComputerDNS.LOG") -Append | |
| "Execute Local Password Reset For $localComputerName\Administrator From '$sAMAccountName'" | Out-File $(Join-Path $currentScriptFolderPath "NTDSUTIL-SYNC-DSRM-PWD-ON-$dcType`s-FROM-DOMAIN-ACCOUNT-$fqdnLocalComputerDNS.LOG") -Append | |
| $ntdsutilOutput = NTDSUTIL "SET DSRM PASSWORD" "SYNC FROM DOMAIN ACCOUNT $computerADDomainName\$sAMAccountName" Q Q | |
| $ntdsutilOutput | Out-File $(Join-Path $currentScriptFolderPath "NTDSUTIL-SYNC-DSRM-PWD-ON-$dcType`s-FROM-DOMAIN-ACCOUNT-$fqdnLocalComputerDNS.LOG") -Append | |
| If ($ntdsutilOutput -like "*Password has been synchronized successfully*") { | |
| If ($dcType -eq "RWDC") { | |
| If ($scriptMode -eq "ADSIorSDSP") { | |
| $adsiSearcher = New-Object DirectoryServices.DirectorySearcher | |
| $adsiSearcher.SearchRoot = [ADSI]"LDAP://$fqdnLocalComputerDNS/OU=Domain Controllers,$adDomainDN" | |
| $adsiSearcher.Filter = "(dNSHostName=$fqdnLocalComputerDNS)" | |
| $rwdcComputerAccountObject = $adsiSearcher.FindOne() | |
| $rwdcComputerAccountDN = $rwdcComputerAccountObject.Properties.distinguishedname[0] | |
| $rwdcComputerAccountObject = [ADSI]"LDAP://$fqdnLocalComputerDNS/$rwdcComputerAccountDN" | |
| $rwdcComputerAccountObject.Put($resetAcknowledgementAttribute, "DSRM => Version: $versionOnRWDC | Org Date/time: $orgDateTimeOnRWDC") | |
| $rwdcComputerAccountObject.SetInfo() | |
| } | |
| If ($scriptMode -eq "ADPoSH") { | |
| Set-ADComputer -Identity $localComputerName -Replace @{$resetAcknowledgementAttribute = "DSRM => Version: $versionOnRWDC | Org Date/time: $orgDateTimeOnRWDC"} -Server $fqdnLocalComputerDNS | Out-File $(Join-Path $currentScriptFolderPath "NTDSUTIL-SYNC-DSRM-PWD-ON-$dcType`s-FROM-DOMAIN-ACCOUNT-$fqdnLocalComputerDNS.LOG") -Append | |
| } | |
| } | |
| If ($dcType -eq "RODC") { | |
| $rodcComputerAccountObject = [ADSI]"LDAP://$fqdnLocalComputerDNS/$rodcComputerAccountDN" | |
| $rodcComputerAccountObject.Put($resetAcknowledgementAttribute, "DSRM => Version: $versionOnRWDC | Org Date/time: $orgDateTimeOnRWDC") | |
| $rodcComputerAccountObject.SetInfo() | |
| } | |
| } | |
| } Else { | |
| Write-Host "SKIPPING Local Password Reset For $localComputerName\Administrator From '$sAMAccountName'" -Foregroundcolor Yellow | |
| Write-Host "The Version of The 'unicodePwd' Attribute Of The AD Account '$sAMAccountName' On The Local RODC Is Different Than The Version On The Source RWDC '$sourceRWDCFQDN'!" -Foregroundcolor Yellow | |
| Write-Host "" | |
| "SKIPPING - Version of 'unicodePwd' Attribute Of AD Account '$sAMAccountName' On Local RODC Is Different Than Version On Source RWDC '$sourceRWDCFQDN'!" | Out-File $(Join-Path $currentScriptFolderPath "NTDSUTIL-SYNC-DSRM-PWD-ON-$dcType`s-FROM-DOMAIN-ACCOUNT-$fqdnLocalComputerDNS.LOG") -Append | |
| } | |
| } Else { | |
| Write-Host "SKIPPING Local Password Reset For $localComputerName\Administrator From '$sAMAccountName'" -Foregroundcolor Yellow | |
| Write-Host "AD Account '$sAMAccountName' Either DOES NOT Exist, Cannot Be Found, Is Inaccessible, Or Control Attribute '$controlAttribute' DOES NOT Have The Correct Value!" -Foregroundcolor Yellow | |
| Write-Host "" | |
| "SKIPPING - AD Account '$sAMAccountName' Either DOES NOT Exist, Cannot Be Found, Is Inaccessible, Or Control Attribute '$controlAttribute' DOES NOT Have The Correct Value!" | Out-File $(Join-Path $currentScriptFolderPath "NTDSUTIL-SYNC-DSRM-PWD-ON-$dcType`s-FROM-DOMAIN-ACCOUNT-$fqdnLocalComputerDNS.LOG") -Append | |
| } | |
| "Ending DSRM Account Sync | $fqdnLocalComputerDNS | $dateTime" | Out-File $(Join-Path $currentScriptFolderPath "NTDSUTIL-SYNC-DSRM-PWD-ON-$dcType`s-FROM-DOMAIN-ACCOUNT-$fqdnLocalComputerDNS.LOG") -Append | |
| "" | Out-File $(Join-Path $currentScriptFolderPath "NTDSUTIL-SYNC-DSRM-PWD-ON-$dcType`s-FROM-DOMAIN-ACCOUNT-$fqdnLocalComputerDNS.LOG") -Append | |
| "+++++" | Out-File $(Join-Path $currentScriptFolderPath "NTDSUTIL-SYNC-DSRM-PWD-ON-$dcType`s-FROM-DOMAIN-ACCOUNT-$fqdnLocalComputerDNS.LOG") -Append | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment