[AD 2.2] The Census, Automated

Nobody wants to read domain controller logs for a month by hand. Invoke-ADPinCensus turns on the instruments, collects across the window, and hands back one dependency report with the rows pre-populated and the dispositions left to you. What it does, what it deliberately does not, and how to run it.


The previous build sheet gave you the whole census by hand: the audit settings, the log queries, the sweeps, the reading. It is correct and it is thorough and almost nobody will run it as written, because it asks a busy admin to go into three event logs on two domain controllers twice a week for a month and correlate the results in a spreadsheet. So we built the thing that does the tedious part. It is one PowerShell script, it lives in a public repository, and its whole job is to turn a month of log-reading into a report you can act on. The judgment stays yours. The transcription does not.


Why this did not already exist

When we scoped this, we looked hard for an existing tool, because writing one is only worth it if the gap is real. It is. There are good tools for pieces of the problem: an excellent, actively maintained Group Policy analyzer, a decade-old Microsoft script that turns LDAP query logs into pivot tables, a handful of frozen parsers for unsigned binds. What does not exist anywhere, free or paid, is the thing that assembles the whole census: turn on the instruments, collect across a window, correlate every finding by source and account, and emit one report that says here is everything that still needs this domain. The security posture scanners come closest and still answer a different question. That distinction is the entire point of a decommission census, and it is the gap this script fills.

What it does, in four modes

The script mirrors the shape of the census itself. You enable the instruments once, collect repeatedly across the window, and report at the end. A fourth mode stands the instruments back down.

ModeWhenWhat it does
-EnableInstrumentsOnce, at the startSets the LDAP diagnostic level and the Kerberos ticket audit subcategory on every domain controller. Prints, but does not set, the two NTLM audit policy values, because writing into the Default Domain Controllers Policy is a decision you make, not one a script makes for you.
-CollectTwice a week, plus once after month-endReads NTLM, LDAP and Kerberos events from the DCs, samples file server sessions, sweeps services, scheduled tasks, managed service accounts and directory attributes, snapshots the DHCP and DNS dependencies. Writes one timestamped JSON snapshot. Reads only; changes nothing.
-ReportAt the end of the windowMerges every snapshot into one CSV and one HTML report: a row per distinct dependency, with first seen, last seen, how many times it appeared, and a suggested handling stage. The disposition column is left blank on purpose.
-DisableInstrumentsWhen the window closesReturns the LDAP diagnostic level to zero. Leaves NTLM auditing and the Kerberos subcategory on, deliberately, because both are cheap and you want them anyway.

Two design choices are worth calling out because they are deliberate. The script never touches the NTLM audit policy, it only tells you the two settings to configure by hand, because a tool that silently edits your domain-wide policy is a tool people are right not to trust. And every collector is wrapped so that a failure becomes a finding rather than a crash: if the script cannot reach a file server, that unreachable server shows up in the report as its own row, because a source you could not measure is not a source you can call clean.

Running it

Get the script from the repository, run it from a management workstation with the RSAT Active Directory tools and rights to read the domain controllers’ event logs. Enable once:

.\Invoke-ADPinCensus.ps1 -EnableInstruments

It will finish by printing the two NTLM settings for you to configure in Group Policy. Do that, then let the estate run. Across the next thirty days, collect on a rhythm, naming the servers you want session and account sweeps on:

.\Invoke-ADPinCensus.ps1 -Collect -FileServers FS01 -MemberServers FS01,SQL01,NPS01

Run that twice a week, and make sure one run lands after your month-end, for the reason the by-hand sheet gives. Each run drops a snapshot into a folder. When the window closes, report:

.\Invoke-ADPinCensus.ps1 -Report

You get PinCensus-Report.csv for working the list and PinCensus-Report.html for reading it. Every row carries a PIN identifier by class, so the first printer’s nightly bind lands as PIN-LDAP-01 and the nightly export job as PIN-SVC-01, matching the naming in the by-hand build sheet. Then stand the noisy instrument down:

.\Invoke-ADPinCensus.ps1 -DisableInstruments

What it deliberately does not do

Four parts of the census stay manual, and their absence from the script is a choice rather than a gap. Group Policy analysis belongs to Intune’s Group Policy analytics and the community GPO tools, which grade against cloud equivalents in a way a census script has no business reinventing. The SQL authentication check is three lines of T-SQL that must run from a real client to give a true answer, so the build sheet has you run it there. The certificate authority census is a certutil call whose output you want to read with your own eyes. And the planted-instrument test, the one where you deliberately trigger an authentication to prove the logging catches it, is the one step that must be done by a human who knows what they planted. A tool that faked any of these would be worse than one that leaves them to you, because it would let you believe the census was complete when it was not.

An honest caveat, and what it is worth to you

This script is published the way we publish tools: it verifies clean, its report logic is tested, and it has not yet been run end to end against a live production estate. Treat your first run as the validating pass, and if something in your environment surprises it, the repository is where that gets fixed. What it buys you is a month of the most tedious work in the migration handed to something that does not get bored on day nineteen and miss the one bind that mattered. The report it hands back is the same inventory the by-hand build sheet produces, minus the eye strain, with the dispositions still yours to decide. Assign them, and Stage 1 begins.


AD to Azure
‹ Previous: [AD 2.1] Build Sheet: The AD Dependency Inventory
Next: [AD 3] Identity: Cutting the Sync