Add dmc-prepop AD module (9 queries via ldap3)#19
Draft
adamswbrown wants to merge 2 commits into
Draft
Conversation
Implements all 9 queries from the AD pre-population spec via Python ldap3: servers (Query 1), computer SPNs (2), service-account + gMSA SPNs (3), sites (4), subnets (5), OU distribution (6), stale servers (7), domain controllers (8), and the single-row coverage summary (9). Adds the `ad` subcommand to the existing dmc-prepop CLI alongside `sccm`. SPN service classes are mapped to friendly workload labels (SQL Server, Exchange, RDS, etc.) per the spec's reference table.
Removes dataclasses.field and typing.Iterable imports that became unused during the AD module addition. No behaviour change.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
dmc-prepop, alongside the existing SCCM module.ldap3.dmc-prepop adsubcommand. Same conventions assccm: streaming CSV with UTF-8 BOM, hostname normalisation, JSON coverage summary,--timestamp-outputfor snapshots.Architecture
dmc_prepop/ad/connect.py— LDAP session helper. Default LDAPS to a DC; supports simple bind (--user/--password) and Kerberos SASL (--auth kerberos). Auto-detects base DN from rootDSE.--gcswitches to Global Catalog (3268/3269) for forest-wide queries.dmc_prepop/ad/spn.py— SPN parser (<class>/<host>[:port][/svcname]) plus aWORKLOAD_BY_CLASSlookup table mirroring the spec's SPN reference (MSSQLSvc→ SQL Server,HTTP→ Web,exchangeMDB/exchangeRFR/SMTPSVC→ Exchange,TERMSRV→ RDS, etc.). ThehostSPN is taggedignoreper spec.dmc_prepop/ad/extract.py— All 9 queries as small functions, plus an orchestrator. Helpers for Windows-filetime conversion (lastLogonTimestamp→ datetime), DN parsing (OU=…extraction), anduserAccountControlbit decoding (DISABLED bit 2, SERVER_TRUST_ACCOUNT bit 8192 for DC detection).dmc_prepop/coverage.py— Extended to include anadsection incoverage_summary.jsonand to write the spec-required flatad_coverage_summary.csv(Query 9) by reading the other AD CSVs.dmc_prepop/cli.py— Adds theadsubcommand. Refactors the shared_resolve_outhelper out ofsccm.Outputs (10 files)
ad_servers.csvad_spns_computer.csvad_spns_service_accounts.csvad_spns_gmsa.csvad_sites.csvCN=Sites,CN=Configuration,….ad_subnets.csvad_ou_distribution.csvad_stale_servers.csvad_domain_controllers.csvuserAccountControl & 8192.ad_coverage_summary.csvLDAP filter translations (PowerShell → ldap3)
The spec is PowerShell + RSAT; this module re-implements equivalent filters as raw LDAP. Notable translations:
Enabled -eq 'True'→(!(userAccountControl:1.2.840.113556.1.4.803:=2))(LDAP_MATCHING_RULE_BIT_AND, ACCOUNTDISABLE flag)Get-ADDomainController→(userAccountControl:1.2.840.113556.1.4.803:=8192)(SERVER_TRUST_ACCOUNT bit)Get-ADReplicationSite→ searchCN=Sites,CN=Configuration,<base>for(objectClass=site)Get-ADReplicationSubnet→ searchCN=Subnets,CN=Sites,…for(objectClass=subnet)Get-ADServiceAccount→(|(objectClass=msDS-GroupManagedServiceAccount)(objectClass=msDS-ManagedServiceAccount))— covers both gMSA and legacy sMSAlastLogonTimestampfiltering uses Windows file-time (100ns ticks since 1601-01-01 UTC); converted via_filetime_cutoff().Spec adherence notes
LastLogonTimestampreplication caveat documented in README; 9–14 day lag is acceptable for migration assessment.--serveror by binding to the GC with--gcfor forest-wide reads.Smoke tests run
ldap3dependency.dmc-prepop --helpshows bothadandsccmsubcommands.dmc-prepop ad --helprenders all options correctly.managedByCN.ALL_QUERIES; SCCM module unaffected.Test plan
pip install -e dmc-prepopsucceeds with the newldap3depdmc-prepop ad --helprendersdmc-prepop ad --server dc01.<domain> --user '<dom>\\reader' --password '...' --out output/ad_servers.csv: confirm hostname normalisation (lowercase, NetBIOS) and OU column populatedad_spns_computer.csvandad_spns_service_accounts.csv: spot-checkMSSQLSvcrows resolve toWorkload = SQL Serverad_domain_controllers.csvmatches the actual DCs in the domainad_stale_servers.csvis sorted descending byLastLogonDaysad_coverage_summary.csvrow totals match the underlying CSVs--gcagainst a Global Catalog and confirm forest-wide results--auth kerberosfrom a host with a valid TGT (Linux withkinitor domain-joined Windows)https://claude.ai/code/session_01JgkCjwqTFGQBra1unq3d8v
Generated by Claude Code