Overview of RID pools for the domain

A short one today. A customer had concerns about the RID Pool administration in his domain. Brief refresher: DCs create security principals such as users, computers and groups, and each one of these must have a unique security identifier a.k.a. as SID. A SID for a domain security principal is built from two parts: the domain SID, and a relative identifier (integer) called a RID. Each DC gets its own unique pool of 500 RIDs to distribute, and when there are 100 or less left over, the DC asks a new pool of 500 RIDs in reserve. Asks it where? At the RID master, of course. If you want to know more, the details are here.

I wrote a quick script to get an overview of the RID pools for all DCs of the current domain:

$properties = "ridAllocationPool","rIDNextRID","rIDPreviousAllocationPool","ridUsedPool"
Get-ADDomainController -Filter * | ForEach-Object {
$dc = $_.hostname
if (-not (Test-NetConnection -ComputerName $dc -Port 389 -ErrorAction SilentlyContinue).TcpTestSucceeded)
Write-Warning "Cannot reach $dc on LDAP, skipped."

$ridsetDN = "CN=Rid Set,$($_.ComputerObjectDN)"
try {
$ridobject = Get-ADObject -Server $_.hostname -filter * -SearchBase $ridsetDN -SearchScope Base -Properties $properties
} catch {
Write-Warning "DC $dc has no RID Pool. It's an RODC or dcpromo has not completed yet."

$poolEnd = ($ridObject.rIDPreviousAllocationPool -band 0xffffffff00000000) / 0x100000000
$poolStart = $ridObject.rIDPreviousAllocationPool -band 0xffffff
$nextPoolEnd = ($ridObject.ridAllocationPool -band 0xffffffff00000000) / 0x100000000
$nextPoolStart = $ridObject.ridAllocationPool -band 0xfffffff

[PSCustomObject] @{
hostname = $dc
nextRid = $($ridObject.ridNextRid)
poolStart = $poolStart
poolEnd = $poolEnd
nextPoolStart = $nextPoolStart
nextPoolEnd = $nextPoolEnd
} | Out-GridView

We start with getting a list of all DCs. We need to visit each one, because some attributes that we need are local to the DC and are not replicated. This is about a large domain, so I needed to filter out DCs that may be offline or even firewalled. The Test-Netconnection commandlet does this for me. Note that this only exists on 2012 R2 and higher. The next thing that tripped me up was the occasional RODC that has no RID administration (why not?). The final bit of trickery is extracting two RID pools: the current one held in attribute rIDPreviousAllocationPool (yes, I know... unfortunate naming) and the next one in ridAllocationPool. These attributes are both 64-bit integers where the low part has the start, and the high part the end of the pool. At the end, we put the data in the pipeline for further processing. In this case we view the data using Out-Gridview, but feel free to use Export-CSV instead to save the data into a convenient CSV file.

The result looks like this in one of my test domains:

Rid Pool Illustration

All RID pools are close to each other. DC6 and DC7 have the same values for the current pool and the next one, meaning that they have not asked for the next pool yet. DC4 is different. As you can see from nextRid which indicates the next RID to be used for SID creation, it is issuing from the final 100 of the current pool, and has already retrieved the next pool. On average, 1 of 5 DCs will have a next pool already allocated, so that my domain of three DCs has a DC with different pools is a lucky coincidence.