Skip to main content

RODC Password Replication Policy

I have been fortunate enough to be involved in quite a large RODC deployment in a Windows 2008 domain. Even more fortunate is that we are currently upgrading this domain to R2 so I am getting the chance to try out the new powershell 2 AD cmdlets.

I have been looking quite a lot into RODC operations, and the importance of the Password Replication Policy (PRP from now on) component has become increasingly more apparent. My first thoughts of PRP were entirely user based. "It allows users to logon to a remote site when the WAN link is down" was my impression. But, when a user logs on to a domain from a trusted computer, there is 2 parts to the authentication - user AND computer. Therefore it is just as important to add the computer objects to the allow PRP as it is the users. While you are there, add any server that is in the same site as the RODC as they will need to authenticate too. My preferred way of doing this create 3 groups and add them to the PRP policy : all users, all computers (user workstations) and all servers

Creating, populating and adding the groups is going to be specific to each environment, so my only advice is to keep your groups / OU's / other AD objects as uniform as possible as it eases the scripting process.

Now we have our groups in the allow PRP list, how can we check to make sure all the groups are there?

Powershell 2 with an R2 (read-write) domain controller allows us use the new AD cmdlets. First let's see how easy it is to get all the RODC's in the domain :

Get-ADDomainController -filter { isreadonly -eq $true }

now, get the PRP for each RODC
$(Get-ADDomainController -filter { isreadonly -eq $true }) | Get-ADDomainControllerPasswordReplicationPolicy

WOW, that’s what I call a cmdlet! Thank goodness for TAB-completion! This gives us a list of allowed groups for each RODC's. This then needs to be compared to the list of groups that is expected to be there. A scriptable way would be to generate a list based on the RODC name, but as mentioned above, this of course relies on your infrastructure being named in a uniform and predictable manor.

TIP: you can give a group a samAccountName that is different to the group name which then can be used for scripting purposes.

So, in the following script, I read the first 6 characters of the RODC (my identifier) and generate my 3 groups in $list. I then compare the memberships and add any groups that are not present :

#loop round all RODC’s
foreach ($RODC in $(Get-ADDomainController -filter { isreadonly -eq $true })) {

   #get the first 6 characters of the RODC
[string]$sitename = $($,6)

   #generate the group list
   $list = "$($sitename)-servers","$($sitename)-computers","$($sitecode)-users"

   #extract the samaccountname from all the groups in the PRP of the RODC
   $allowedPolicy = $(Get-ADDomainControllerPasswordReplicationPolicy -id $rodc -allowed) | select "samaccountname"

   #loop round all the groups that were created above
   Foreach ($group in $list) {

      #check to see the $allowedpolicy groups does not include the current group
      If ($($allowedPolicy | % {$_.samaccountname}) -notcontains $group){

         #if it is not part of the list, add it
         Add-ADDomainControllerPasswordReplicationPolicy -identity $RODC -AllowedList $group


  1. Erk, I hope your domain controllers aren't Core....

  2. Only the RODC's, which are in the process of being upgraded to R2! Interesting situation though, as all the dependancies required to run AD cmdlets, PS remoting etc are becoming available for other OS's you would naturally think that it would be all systems go. But, in a 'most secure' configuration for AD's using server core, this would put a spanner in the works until a complete OS upgrade was possible.


Post a Comment

Popular posts from this blog

PowerShell 3 behavioural change

It's taken me way too long to get into PowerShell 3, I guess opportunity hasn't shown it's self until now and so, here, my V3 journey begins.

I was asked to debug a script that would run fine in PS v2 and not in v3.  The issue was a that a variable length was being checked and was failing in v3.  This is why...

In v2 if a variable is undefined, this test returns false

PS C:\windows\system32> $var.length -eq 0

In v3 the same test returns true....

PS C:\windows\system32> $var.length -eq 0

Not a biggie, but as in this case, a script has broken so something to consider!



Enable Powershell Remoting (WinRM) via Group Policy

I have been doing some testing on enabling WinRM via group policy, being that WinRM is the service that Powershell v2 sets up it remoting capabilities. Here are the GPO settings that you need to configure WinRM ....

set the winrm service to auto start

Computer Configuration \ Policies \ Windows Settings \ Security Settings \ System Services

Windows Remote Management (WS-Management)  set Startup Mode to Automatic

start the service

incorporated in to the above - you may need a restart.

create a winrm listener

Computer Configuration / Policies / Administrative Templates / Windows Components / Windows Remote Management (WinRM) / WinRM Service / Allow automatic configuration of listeners

IPv4 filter: *

* is listen on all addresses, or if you only want a particular IP address to respond use an iprange eg - don't forget that this IP range has to be valid for all hosts that fall in the scope of the GPO you are creating.  You can use -, - …

compare-object in Powershell - comparing mulitple values

I'm starting to use compare-object more and more, and one thing I noticed, is that you can compare 2 objects based on multiple attributes. here is how it is constructed...
Compare-Object -ReferenceObject $object1 -DifferenceObject $object2 -Property a,b,c,d,eIf a,b,c and d are the same, but e is different, compare object will return a difference. In the following example, I use "-eq $null" as a check because by default compare-object returns $null if the objects are the same.
#create an array of objects to check against

$collection = @()
foreach ($entry in ("aaaaa","bbbbb","ccccc","ddddd")){
   $store = "" | select "a","b","c","d","e"
   $store.a = $entry*1
   $store.b = $entry*2
   $store.c = $entry*3
   $store.d = $entry*4
   $store.e = $entry*5
   $collection += $store

#create an object similar to those in the array
$object = "" | select "a","b…