terraform-provider-ad
terraform-provider-ad copied to clipboard
Do not complete apply until object is replicated
Description
When using Active Directory replication, a new object created a one location needs to be replicated to one or more other locations. In this scenario, when the object is created, it may also be needed at the replication targets for the workflow to continue successfully.
Potential Terraform Configuration
References
https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/get-started/replication/active-directory-replication-concepts
Community Note
- Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
- If you are interested in working on this issue or have submitted a pull request, please leave a comment
Question :
Should the replication be enforced or wait until normal replication is done ?
Got a piece of code to force replication (and ensure it's replicated on all DC's). I'm still not sure if it's the best approach to take.
Here is the code, feel free to comment :
function Sync-DomainController {
[CmdletBinding()]
param(
[string] $Domain = $Env:USERDNSDOMAIN
)
$DistinguishedName = (Get-ADDomain -Server $Domain).DistinguishedName
(Get-ADDomainController -Filter * -Server $Domain).Name | ForEach-Object {
Write-Verbose -Message "Sync-DomainController - Forcing synchronization $_"
repadmin /syncall $_ $DistinguishedName /e /A | Out-Null
}
}
function Get-WinADForestReplicationPartnerMetaData {
[CmdletBinding()]
param(
[switch] $Extended
)
$Replication = Get-ADReplicationPartnerMetadata -Target * -Partition * -ErrorAction SilentlyContinue -ErrorVariable ProcessErrors
if ($ProcessErrors) {
foreach ($_ in $ProcessErrors) {
Write-Warning -Message "Get-WinADForestReplicationPartnerMetaData - Error on server $($_.Exception.ServerName): $($_.Exception.Message)"
}
}
foreach ($_ in $Replication) {
$ServerPartner = (Resolve-DnsName -Name $_.PartnerAddress -Verbose:$false -ErrorAction SilentlyContinue)
$ServerInitiating = (Resolve-DnsName -Name $_.Server -Verbose:$false -ErrorAction SilentlyContinue)
$ReplicationObject = [ordered] @{
Server = $_.Server
ServerIPV4 = $ServerInitiating.IP4Address
ServerPartner = $ServerPartner.NameHost
ServerPartnerIPV4 = $ServerPartner.IP4Address
LastReplicationAttempt = $_.LastReplicationAttempt
LastReplicationResult = $_.LastReplicationResult
LastReplicationSuccess = $_.LastReplicationSuccess
ConsecutiveReplicationFailures = $_.ConsecutiveReplicationFailures
LastChangeUsn = $_.LastChangeUsn
PartnerType = $_.PartnerType
Partition = $_.Partition
TwoWaySync = $_.TwoWaySync
ScheduledSync = $_.ScheduledSync
SyncOnStartup = $_.SyncOnStartup
CompressChanges = $_.CompressChanges
DisableScheduledSync = $_.DisableScheduledSync
IgnoreChangeNotifications = $_.IgnoreChangeNotifications
IntersiteTransport = $_.IntersiteTransport
IntersiteTransportGuid = $_.IntersiteTransportGuid
IntersiteTransportType = $_.IntersiteTransportType
UsnFilter = $_.UsnFilter
Writable = $_.Writable
}
if ($Extended) {
$ReplicationObject.Partner = $_.Partner
$ReplicationObject.PartnerAddress = $_.PartnerAddress
$ReplicationObject.PartnerGuid = $_.PartnerGuid
$ReplicationObject.PartnerInvocationId = $_.PartnerInvocationId
$ReplicationObject.PartitionGuid = $_.PartitionGuid
}
[PSCustomObject] $ReplicationObject
}
}
function Start-ADSync
{
$now = Get-Date
Write-Output "Starting sync at $now"
$sync = $false
do
{
# Force sync
Sync-DomainController
# Ensure replication is applied on all AD
$results = Get-WinADForestReplicationPartnerMetaData
Write-Output "----"
foreach ($result in $results) {
if ($result.LastReplicationSuccess -gt $now) {
Write-Output "[Sync OK] Started: $now < ended successfully: $($result.LastReplicationSuccess)"
$sync = $true
}
else {
Write-Output "[Sync KO] Started: $now > ended successfully: $($result.LastReplicationSuccess)"
$sync = $false
}
}
Write-Output "----"
}
until ($sync)
return "Sync finished on all DC's"
}
Start-ADSync
Source for the functions : evotec.xyz
About this request,
Got a few points that i'd like to clarify :
- Do we consider the replication as mandatory or do we give the choice to the user to enable it (via a setting in the provider for example) ?
- Do we trigger a manual replication on all DC''s or do we check/wait for normal replication process to be finished ?
- If we force replication, do we synchronize all objects or only objects that were created/modified ?
- Is replication useful when object are deleted ?
My two cents on that :
I would trigger the replication manually from the domain controller the server is connected to ($env:LOGONSERVER) all other domain controllers. I would trigger a sync after each object create and update using cmdlet Sync-ADObject (Link) I would force a sync of all object after a deletion of object only.
Comments are welcome. I don't know if there is a perfect way to implement this...
Another option would be to select one of the domain controllers and only work with that one server and let natural replication happen. Something like (Get-ADDomainController | Select-Object -First 1).HostName
would work. You could even tie it to a switch like persistant_dc
. I would love to see this implemented, where I work has a rather large replicated AD environment but with the way the module is now I can't use it. Constantly get the errors stating the object was present but is now absent