8000
Skip to content

Latest commit

 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

ADOutline

Active Directory Current-State Documentation

Know exactly what you have. One command, one file, about twenty seconds.

ADOutline answers a question every organisation should be able to answer on demand and most cannot: what is actually configured in our Active Directory right now?

It reads the directory and writes the answer down — 47 sections and 11 diagrams in a single HTML file that anyone can open, email, archive, or attach to a ticket. No agents. No installation. No data leaves your network.

It is documentation, not an assessment. No scores, no grades, no traffic lights, no recommendations. It records what is configured and leaves the judgement to the people qualified to make it.


Why it matters

Active Directory is usually the oldest system in the building and the least documented. It has been upgraded, merged, migrated and inherited across decades and staff changes. The people who made the original decisions have often left. What remains is a system everything else depends on, that nobody can fully describe.

That gap becomes expensive at exactly the wrong moments:

  • An acquisition or divestiture, where someone has to describe two directories before they can be joined or separated
  • A migration or modernisation programme, where the plan is only as good as the picture of what exists today
  • An audit or a cyber-insurance questionnaire, where "we believe so" is not an acceptable answer
  • A handover — to a new team, a new MSP, or a new owner
  • A ransomware tabletop or DR test, where the first question is what the environment looks like when it is working

ADOutline produces that description in twenty seconds, as a file, that a person who does not administer Active Directory can still read.

It is strictly read-only. No AD object, registry value, GPO or file is modified. Nothing is transmitted anywhere. It can be run during business hours without a change ticket.


Why engineers use it

Most tools answer a question you didn't ask. They score you, or they need RSAT and a domain-joined jump box, or they want an agent, or they hand back a spreadsheet you still have to interpret.

ADOutline talks to the directory over LDAP directly rather than through the ActiveDirectory module, so it needs no RSAT and installs nothing. That means it runs from a non-domain-joined machine over a customer VPN with -Server and -Credential — usually the difference between collecting on day one and waiting a week for a jump box to be provisioned.

Run it once. Open the HTML. Send it to whoever needs it.


Why a single script, not a module

Because this tool's job is to run once, in an environment you do not control, often on a machine somebody else owns.

Single script Module
Getting it there Email it, paste it into an RDP session, drop it on a share PSGallery access, or unpack to a module path, or Import-Module .\path
Security review One file. The customer's security team can read all of it before it touches a domain controller Review a package, then trust the install
Install footprint None. Nothing is written outside the output folder Files placed on the machine
Change ticket Usually not needed Usually needed
Prerequisites Windows PowerShell 5.1. Nothing else Module present, correct version, right path

A module is the better shape for software you run repeatedly in your own environment — better testing, cleaner diffs, shared code, Install-Module. Those are real advantages and this project pays for not having them.

But for a tool whose entire pitch is read-only, installs nothing, sends nothing anywhere, being a single inspectable artifact is not a packaging decision. It is part of what is being claimed. "Here is the whole thing, read it before you run it" is a materially easier conversation with a security team than "please approve this package from the internet" — and that conversation is frequently what stands between collecting today and collecting next week.

The rest of the suite works the same way, for the same reason.


The series

Tool What it answers
ADOutline Document the current state
ADAtlas See the environment
ADCanvas Understand the environment
ADLens Track how it changes

ADAtlas draws the picture. ADCanvas judges the health. ADOutline writes down the facts — and writes them into a state file you can re-render or compare later.


What it records

47 sections, 11 interactive diagrams, one HTML file.

Forest and topology

  • Forest & Domains Map, Trust Map, Replication Topology, FSMO Placement, Site Topology — all drawn as interactive SVG, all clickable
  • Domain functional levels, trust attributes decoded, site links by cost
  • Per-DC capability map: which controller answered on which protocol

Object population

  • Users, computers and groups counted by state — enabled, disabled, locked, password-never-expires, unconstrained delegation, no-preauth, adminCount, inactive at 90/180/365 days
  • Counts are produced by a streaming paged read that discards every object as it goes, so memory stays flat regardless of estate size

Identity platforms

  • One node per platform on the forest map, linked to the root, with every independent signal folded in as evidence
  • Entra Connect, Okta, Ping, SailPoint, JumpCloud, Duo, Google Cloud Identity, AD FS — detected from directory objects, published SCPs, and agents installed on a domain controller
  • Tenant and organisation names extracted where the directory publishes them

Lineage and migration history

  • Adprep operation clusters dating each upgrade event
  • Dated milestone containersProtected Users is 2012 R2, Key Admins is 2016, and each container's creation date is the date that domainprep ran
  • Schema extension timeline — every schema object grouped by creation date, so Exchange, SCCM and legacy LAPS each date themselves
  • Migration artifacts — the <NetBIOS>$$$ group ADMT's password export step requires, and the sIDHistory it left behind
  • Functional-level raise history from replication metadata
  • FRS remnants alongside DFSR, and Pre-Windows 2000 Compatible Access membership

Security-relevant configuration

  • LAPS — legacy Microsoft LAPS vs Windows LAPS by generation, expiry analysis, encrypted vs plaintext, policy read from the registry
  • dMSA migration state and superseded account linkage
  • Kerberos policy, encryption types, KRBTGT age, FGPP, AdminSDHolder
  • Backup state from dSASignature, not a registry key that doesn't exist
  • Time hierarchy — configured vs effective source, with the forest apex shown

Supporting services

  • DNS Architecture and DNS Zone Replication — zone type is recorded per server, because the same zone is commonly Primary on one DC and Secondary on another
  • PKI hierarchy, Exchange architecture, NTP hierarchy, OU hierarchy
  • DHCP authorisation, AD FS farms, LSA packages, custom password filters

What ADOutline does NOT do

  • Score, grade or rank anything
  • Recommend remediation
  • Modify any AD object, registry value, GPO or file — it is strictly read-only
  • Require RSAT or the ActiveDirectory module
  • Require WinRM or PowerShell remoting
  • Send data anywhere
  • Scan member servers or workstations. It reads the directory and the domain controllers, and nothing else

If you want a picture, use ADAtlas. If you want health analysis, use ADCanvas. If you want the facts written down, use ADOutline.


Requirements

Requirement
PowerShell Windows PowerShell 5.1 or newer
Modules None. System.DirectoryServices.Protocols ships with .NET
Network LDAP (389) to a DC in each domain
Host Any Windows machine with line of sight to the DCs. Does not need to be domain-joined and does not need to run on a DC

Collection tiers and rights

ADOutline collects in three tiers. Each degrades independently — losing one never stops the others, and the report states which sections were affected.

Tier Method Rights Covers
A LDAP Domain User ~80% of the report
B SMB to SYSVOL Domain User GPO templates, Kerberos policy
C CIM / DCOM to each DC Local Administrator on the DC DC hardware, services, hotfixes, registry, event log summaries

Every report includes a Permissions Required by Section table recording which rights each section needed and whether they were available — so an empty section caused by missing access is never mistaken for an empty environment.


Usage

.\ADOutline.ps1

That's it.

From a non-domain-joined machine:

$cred = Get-Credential
.\ADOutline.ps1 -Server dc01.contoso.com -Credential $cred

Directory data only, no local admin needed anywhere:

.\ADOutline.ps1 -SkipTierC

Re-render an earlier collection without touching the directory:

.\ADOutline.ps1 -FromState '.\ADOutline_contoso_com_20260802_143915.state.json'

Parameters

Parameter Default Purpose
-Server Target a specific DC or domain. Required from a non-domain-joined host
-Credential Alternate credentials
-OutputPath script directory Where the report, state file and log are written
-FromState Re-render a saved state file. No directory access at all
-SkipTierC Skip all CIM/DCOM collection
-ExcludeDC Domain controllers to leave alone
-NoProbe Skip the startup capability probe
-NoHtml Collect and write state, but produce no report
-NoState Produce the report but write no state file
-ShowDetail Verbose console output
-LogPath auto Log file location
-PageSize 1000 LDAP page size
-LdapTimeoutSec 30 Hard per-query timeout
-ProbeTimeoutMs 1500 Per-DC TCP probe timeout
-ProbeThrottle 32 Parallel probes
-TierCTimeoutSec 90 Per-DC Tier C timeout
-TierCThrottle 12 Parallel Tier C runspaces
-SkipHotfixScan Skip hotfix enumeration (the slowest Tier C step)
-SkipSoftwareScan Skip installed-software enumeration
-EventDays 7 Days of event log summary to collect

Design notes

A few decisions worth knowing about if you plan to read the source.

RSAT-free by design. System.DirectoryServices.Protocols throughout, never the ActiveDirectory module. This is what makes a non-domain-joined run possible.

Counts, not objects. Populations are counters incremented during a streaming paged read. Tables survive only where the population is bounded by design — DCs, sites, trusts, FSMO, CAs, zones. Nothing accumulates a million DNs in memory.

Capability map with one-way demotion. One parallel TCP probe at startup records which protocols each DC answers on. A real failure demotes that capability, and every later section skips the host for free. Never re-probed.

Hard timeouts everywhere. Every LDAP query and every Tier C runspace has a deadline. A dead DC costs one timeout, not a stall.

Warnings vs Observations. A warning means collection was impaired. An observation is a factual note about the environment. They are never mixed, and neither is scored. "Not deployed" and "not readable" are different answers and are reported differently.

The state file is the interface. Collection owns the state; display only reads it. -FromState re-renders with zero directory access — useful for re-rendering after a report change without going back to the customer, and the raw material for comparing two points in time.


Output

Three files per run:

File Purpose
ADOutline_<forest>_<stamp>.html The report. Self-contained — no CDN, no external assets
ADOutline_<forest>_<stamp>.state.json Everything collected, before rendering
ADOutline_<stamp>.log Timestamped collection log

The HTML is typically 200–600 KB depending on estate size. Open it locally, archive it, attach it to a ticket, or host it as a static file.


1

2

3

4

5

6

7


Contributing

Issues and pull requests welcome. Please test against a real (lab) forest before submitting — this script handles a lot of edge cases that only appear in actual environments, and several of its subtler bugs were only ever found by running it against a live directory.


Author

Santhosh Sivarajan — Microsoft MVP


License

MIT — free to use, modify, and distribute.

Releases

Packages

Contributors

Languages

0