Summary: Microsoft PFE and Honorary Scripting Guy, Ian Farr, discusses using Windows PowerShell to synchronize delegated administrator passwords.
Microsoft Scripting Guy, Ed Wilson, is here. Guest blogger and Honorary Scripting Guy, Ian Farr, is back with us today for the conclusion of his series about read-only domain controllers (RODCs)...
Welcome to the final post in my semi-spontaneous series about managing and securing RODCs.
The first post discussed a function that analyses RODC authentication. The function reports on accounts that are authenticated by an RODC that aren’t revealed (that is, the account password or secret is not stored on the RODC). It helps you manage your password replication policies. For the full write up, see Use PowerShell to Work with RODC Accounts.
The second post discussed a function that checks whether a user is a member of a high-privileged group. It can be used in conjunction with the first function to see if your RODCs have authenticated high-privileged users. This helps identify and remove a potential means of compromising Active Directory. To read that post, see Use PowerShell to Search Active Directory for High-Privileged Accounts.
The third post discussed a function that assists in ensuring that we have low-privileged users delegated as RODC administrators. It populates the RODCs ManagedBy attribute with a designated User or Group. It can easily propagate administrative privilege to a large number of RODCs. Here is that post: Use PowerShell to Delegate Administrator of RODCs.
On to the last post...
This one discusses a function that synchronizes the passwords of our previously delegated administrators.
Why do such a thing?
Without access to an read-write domain controller (RWDC), an RODC is unable to authenticate users or computers if their passwords aren't already stored on the RODC. Here's a scenario:
- An RODC becomes isolated (unable to communicate with a RWDC).
- A delegated admin needs to do some work on the isolated RODC.
- The delegated admin has never previously logged on to the RODC.
- The delegated admin's password has never been prepopulated.
In this scenario, the delegated admin would not be able to get into the RODC until connectivity with a RWDC is resumed. If the admin's password had been prepopulated, the admin could have performed the work.
How does the function work?
The function uses functionality that was introduced in 2012 with the Active Directory Replication cmdlets—namely, the –PasswordOnly parameter of the Sync-ADObject cmdlet. However, before we get to that bit, we need to enumerate the ManagedBy attribute of the RODC’s computer object and check whether we are dealing with a user or group:
$ManagedByPrincipal= Get-ADComputer -Identity $Rodc -Property ManagedBy |
ForEach-Object {Get-ADObject -Identity $_.ManagedBy}
The value in ManagedBy is a DistinguishedName, so we can then use Get-ADObject to retrieve an object and store it in $ManagedByPrincipal. With this variable populated, we check the ObjectClass to see if we are dealing with a user object, a group object, or something else:
If (($ManagedByPrincipal.ObjectClass-ne "user") -and ($ManagedByPrincipal.ObjectClass -ne "group")) {
#Write a message to the host
Write-Host "$ManagedByPrincipal is not a user or group"
} #End of If (($ManagedByPrincipal.ObjectClass-ne "user") -and ($ManagedByPrincipal.ObjectClass -ne "group"))
Else {...}
If we are dealing with a user or group, we now determine the exact ObjectClass in the Else script block. We use the Switch statement to check if we have a user or a group object. If a group is found, we enumerate the members and store the results in $Principals. If a user is found, we assign our original $ManagedByPrincipal to $Principals:
Switch ($ManagedByPrincipal.ObjectClass) {
"group" {
#Hold the enumerated ManagedBy group members in $Principals
$Principals = Get-ADGroupMember -Identity $ManagedByPrincipal -Recursive
} #End of "group"
"user" {
#Hold single ManagedBy principal in $Principals (user object)
$Principals = $ManagedByPrincipal
} #End of "user"
}
Finally, we loop through each element of $Principals and execute the following script, which synchronizes the user’s password to our RODC:
$Principals | ForEach-Object {
Get-ADObject -Identity $_.distinguishedName |
Sync-ADObject -Destination $Rodc -PasswordOnly -PassThru
}
In this script, we get an object that represents the current iteration of $Principals with the Get-ADObject cmdlet and pipe that into the Sync-ADObject cmdlet with our RODC as the destination. The –PasswordOnly parameter synchronizes only the password, as you’d expect.
The function’s –Rodc parameter accepts pipeline input, so we can run a one-liner like this to sync the passwords to a number of RODCs:
Get-ADDomainController -Filter {IsReadOnly -eq $True} | Sync-ADRodcManagedByPassword
Note You should synchronize the passwords of delegated RODC administrative accounts on a regular basis, so that the RODCs have up-to-date passwords.
That’s it for the series…for now, anyway! We’ve looked at four functions to assist with the administration of RODCs:
- Get-ADRodcAuthenticatedNotRevealed
Help refine your password replication policies - Set-ADRodcManagedByAttribute
Delegate RODC administrative privileges - Sync-ADRodcManagedByPassword
Populate delegated administrators’ passwords to a list of RODCs - Test-ADUserHighPrivilegeGroupMembership
Check whether an RODC has authenticated high privileged users
I’ve put the functions from the series into a fledgling module to expedite their usage:
RODC Management PowerShell Module
I've also applied the functions in the following sample script, which produces CSV reports of RODC authentication and high privileged use:
Create RODC Password Replication Policy and High Privileged Usage Reports
TTFN!
~Ian
Thanks for this series on RDOC, Ian! It has been a great and useful series.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy