CBOM Documentation

CBOM Secure

  • Product Overview
    • Overview
    • Dashboard Interface
    • Dashboard Operations
    • Data Visualization
    • Overview
    • Host
    • Template
      • Networked Deployments
      • Cloud Deployments
      • Off-Grid Deployments
    • Discovery History
      • Tags
      • Tag Scope
      • Integrations
      • Cloud Servers
      • CycloneDX Export
    • Sensors Reference
    • Overview
    • Summary Report
    • PQC Report
    • AI Services
    • Source Code Visualizer
    • Key
    • Certificate
    • CipherSuites
    • Analysis
    • Policy Management
    • User Policy
    • Standard Policy
    • Overview
    • Cases
    • Criteria
    • Notification Format
    • Rules
      • Connections
      • Health
    • User Management
    • Roles & Permissions
    • Audit Trail
    • System Logs
    • Top Bar and User Menu
    • System Configuration
  • Login and Authentication
    • Introduction
      • Components
      • Data Flows
      • Execution Models
      • Incremental Scanning
      • Security Model
      • Topologies
      • Sizing Guide
      • HA and Scaling
      • Ports and Firewall
      • Prerequisites
      • Docker Compose
      • Native on Linux
      • Deployment Server
      • Install Troubleshooting
      • Validation Checklist
      • Managing Services
      • Logging
      • Certificates
      • Configuration
      • Backup and Recovery
      • Ops Troubleshooting
      • Methods
      • SAML 2.0 SSO
      • OIDC and Entra ID
      • Token Authentication
      • Password Policy
      • Sensor vs Connector
      • Sensor Guide Structure
      • Capability Matrix
      • GitHub Sensor
        • AWS
        • Azure
        • Google Cloud
        • Active Directory
        • LDAP Directories
        • AD CS
        • Thales Luna HSM
        • Entrust nShield HSM
        • HashiCorp Vault KMIP
        • Windows Cert Store
        • Linux Trust Store
        • MSSQL TDE
      • Roadmap
      • Integration Model
      • CrowdStrike
      • ServiceNow
      • ServiceNow and Jira Setup
      • Notification Engine
  • Administrative Guide
    • Glossary
    • Configuration Reference
    • Data Model Reference
    • API Reference
    • API Authentication
    • CycloneDX Export Specification
    • Risk and PQC Scoring
    • Built-in Standards
    • Widget Catalogue
    • AI Services Data Handling

Active Directory Sensor — Reference

File: DiscoveryManager/Sensors/discover_activedirectory/activedirectory_sensor.py Sensor name: Discover_ActiveDirectory Protocol: LDAP / LDAPS (port 389 / 636) · Global Catalog (port 3268 / 3269) Last updated: 2026-05-06

Status legend

SymbolMeaning
XCompleted — implemented, tested on real AD, output verified
WWorks — implemented and running, limited real-domain testing
DDeveloping — partially coded, not finished
FFuture — not started, planned for a later phase
—Out of scope — not a key/cert, skip by design

1 — Identity objects

Scan targetStatusAD attribute / objectClassWhat is discovered
User certificatesXuserCertificate on objectClass=userX.509 DER certs on user accounts — smart card login, email signing, VPN
Computer certificatesXuserCertificate on objectClass=computerMachine certs issued by AD CS for TLS, 802.1X, etc.
SSH public keysXaltSecurityIdentities on user / computerRSA, ECDSA, Ed25519 public keys stored for LDAP-SSH auth
Windows Hello (NGC) keysXmsDS-KeyCredentialLink on user / computerWHfB asymmetric key pairs — public key, device ID, TPM-backed flag
gMSA (service accounts)Xvia msKds-ProvRootKey (KDS root key)The master key from which all gMSA passwords are derived
Computer machine password—NT hash on the DC — not an LDAP attributeAuto-rotates every 30 days. Stored as NT hash inside NTDS.dit — never exposed over LDAP.
Groups / Contacts / inetOrgPerson——No authentication material

2 — Directory partitions scanned

PartitionStatusBase DNWhat is found there
Domain partitionXDC=corp,DC=test,DC=localUser certs, SSH keys, NGC keys, BitLocker, trusts
Configuration partitionXCN=Configuration,DC=...CA certs, KDS root keys, CRL, cross-cert pairs
Schema partition—CN=Schema,CN=Configuration,...Object definitions only — no keys
Application partition—Domain-specificDNS zones — not in scope

3 — Authentication & security

Scan targetStatusAD attributeWhat is discovered
Kerberos TGT signing keyXkrbtgt — pwdLastSet, msDS-KeyVersionNumberSigns every Kerberos ticket — KVNO, last rotation, RODC vs domain
Domain trust inter-realm keysXobjectClass=trustedDomain in CN=SystemRC4 vs AES algorithm, trust direction, trust attributes
Smart card / cert authXuserCertificateCovered by phase 1 — user certs
Windows Hello for BusinessXmsDS-KeyCredentialLinkCovered by phase 4 — NGC keys
NTLM password hashes—Not exposed via LDAPNever readable over LDAP — not scannable by design
Password policies—GPOPolicy rules, not key material

4 — PKI & cryptography

Scan targetStatusAD attribute / locationWhat is discovered
CA certificates (domain NC)XcACertificate on CA objectsRoot and intermediate CA certs on user/computer objects
CA certificates (config NC)XcACertificate in CN=Public Key ServicesFull PKI hierarchy — root, intermediate, issuing
Cross-certificate pairsXcrossCertificatePair in CN=AIA,...Inter-CA trust certs between this org's CA and external CAs
CRL revocation enrichmentXcertificateRevocationList, deltaRevocationListPre-fetched at scan start — isRevoked: true added to any cert whose serial appears in the CRL
BitLocker recovery keysXmsFVE-RecoveryInformation under computer objectsRecovery GUIDs, volume GUIDs, linked computer — existence metadata only
DPAPI domain backup keysXBCKUPKEY_* in CN=SystemTwo docs per key pair — private_key + public_key, both keyBytesAccessible: false. Algorithm (RSA-2048) is a spec-constant from MS-BKRP §2.2.5 — algorithmSource: "specification" marks this. Actual RSA blob requires LSAD RPC, not LDAP.
KDS root keysXmsKds-ProvRootKey in config NCMaster keys that derive gMSA passwords — version, create/use-start time, Pending/Active state
TPM owner authXmsTPM-InformationObjectOwner-auth blob per computer — _scan_tpm_keys phase. Existence + linked computer.
Certificate templates—CN=Certificate TemplatesConfiguration blueprints only — no keys. Analysis is CBOM server's job.
AD FS token signing certs—Moved to discover_wincertsRemoved from this sensor. AD FS writes no key material to LDAP — certs only accessible via Get-AdfsCertificate PowerShell, which requires running on the AD FS server itself. Use discover_wincerts with scan_adfs: true. See Docs/Sensors/WinCerts-Sensor.md.
AD CS archived private keys—CA JET databaseNot in LDAP. Archived keys live in the CA's JET database encrypted under the CA Exchange cert. certutil -getkey is the only extraction path, requires CA admin. Needs a dedicated discover_adcs sensor. Not extractable via wincerts.
EFS recovery agent certs—SYSVOL GPO XML blobReal cert material but lives on SYSVOL (SMB) — not LDAP. Needs a separate SMB sensor.
Archived private keys (AD CS)—CA server JET databaseNot in LDAP. Needs a separate discover_adcs sensor on the CA server.
OCSP / AIA service certs—HTTP endpoints onlyNot in LDAP — HTTPS sensor concern.

5 — Multi-forest / multi-domain topology

CapabilityStatusNotes
Global Catalog DC discoveryXConnects to GC (port 3268/3269), queries CN=Partitions,CN=Configuration for all domain NCs in the forest, enumerates DCs per domain NC via LDAP filter serverReference + SERVER_TRUST_ACCOUNT.
Child domain scanningXEach DC discovered via GC is appended to the scan queue automatically. Full 10-phase scan runs on each DC.
Tree domain scanningXTree domains (e.g. mergedpartner.local) have independent LDAP roots — discovered via CN=Partitions, not LDAP SUBTREE from forest root. Requires DNS resolution of tree-domain hostnames (conditional forwarder).
Cross-forest trust metadataWTrust key objects scanned per domain. Actual cross-forest credential unreachable over LDAP — metadata only.
GC Config NC workaroundXGC port 3268/3269 does NOT serve the Configuration NC. Sensor opens a secondary connection on port 636 to the same server for CN=Partitions queries — transparent to the user.
Traversal log documentXOne type: "traversal" document emitted at end of every run. Lists every target — server, resolvedIP, resolvedFQDN, outcome, connect errors, phase errors, per-phase cert counts.

6 — Additional AD services

Scan targetStatusNotes
AD FS token-signing / decrypting certs—Moved to discover_wincerts. Sensor must run on the AD FS server or a host with RSAT-ADFS. See Docs/Sensors/WinCerts-Sensor.md.
AD RMS—Rare in modern orgs — separate concern
AD LDS (standalone LDAP)—Separate LDAP sensor
Azure AD Connect / Entra ID—Cloud-side only — on-prem sensor boundary ends here

What the sensor emits

CBOM typekeyTypeSourceNotes
certificate—Domain certs, CA certs, cross-certssubject, issuer, serialNumber (colon-hex), validFrom, validTo, keyUsage bitmask, SignAlgo, publicKey (b64), publicKeySha256, certSha256
keypublic_keyCompanion to every certificatepublicKeySha256, algorithm, size, state. Join to cert via publicKeySha256.
keypublic_keySSH keysSSH wire-format — RSA / ECDSA / Ed25519
keypublic_keyNGC / WHfBTPM-backed WHfB key — device ID, usage, creation time
keysecret_keyBitLocker, KDS, krbtgt, trust keysExistence + metadata — keyBytesAccessible: false where applicable
keyprivate_keyDPAPI backup keysRSA-2048 existence — algorithm from spec (MS-BKRP §2.2.5)
keypublic_keyDPAPI backup keysSibling of the DPAPI private_key doc
status—End of each target scanOutcome (Ok / Partial / Failed), phaseErrors map, per-phase cert counts
traversal—End of entire runAll targets — server, resolvedIP, resolvedFQDN, outcome, certCounts, scan summary

Scan phases — execution order inside discover_all()

discover_all()
│
├── GC expansion        _discover_dcs_via_gc()      GC → CN=Partitions → all domain NCs → all DCs
│                                                   Discovered DCs appended to scan queue
│
│   ── per target ───────────────────────────────────────────────────────
│
├── CRL pre-fetch       _load_revoked_serials()     Base CRL + Delta CRL → revoked serial set
│
├── Query  1            _scan_domain_certs()        userCertificate  (domain NC)
├── Query  2            _scan_config_certs()        cACertificate    (config NC)
├── Query  3            _scan_ssh_keys()            altSecurityIdentities
├── Query  4            _scan_ngc_keys()            msDS-KeyCredentialLink  (WHfB / NGC)
├── Query  5            _scan_bitlocker()           msFVE-RecoveryInformation
├── Query  6            _scan_kds_keys()            msKds-ProvRootKey  (config NC)
├── Query  7            _scan_trust_keys()          trustedDomain  (CN=System)
├── Query  8            _scan_dpapi_keys()          BCKUPKEY_* Secret  (CN=System)
├── Query  9            _scan_krbtgt_keys()         krbtgt account(s)
├── Query 10            _scan_cross_certs()         crossCertificatePair  (config NC)
│
│   Queries 6–10 are skipped on GC targets (DC-only phases).
│   Skipped phase names logged in status doc gcSkippedPhases.
│
├── Status doc          _status_doc()               one per target — counters for all 10 phases
│
└── Traversal doc       (end of discover_all)       one per full run — all targets + outcomes

All LDAP queries use paged search (page size 500). Deduplication by SHA-256 of DER bytes (certs) or deterministic UUID5 seed (keys). PEM normalisation: userCertificate bytes starting with -----BEGIN are decoded to DER by _to_der().

sourceProperties — fields on every document

FieldTypeDescription
hoststringIP / hostname of the DC the sensor connected to
distinguishedNamestringFull LDAP path of the source object
objectClasseslistInheritance chain — most specific class last
adPartitionstringdomain or configuration
adAttributestringLDAP attribute that contained the material
adEntitystringPascalCase label identifying what was scanned
adEntity values
PhaseadEntity
_scan_domain_certsDomainCertificate
_scan_config_certsCACertificate
_scan_cross_certsCrossCertificate
_scan_ssh_keysSSHPublicKey
_scan_ngc_keysWindowsHelloNGCKey
_scan_bitlockerBitLockerKey
_scan_kds_keysKDSRootKey
_scan_trust_keysDomainTrustKey
_scan_dpapi_keysDPAPIBackupKey
_scan_krbtgt_keysKerberosKrbtgtKey
Traversal log — fields per target entry
FieldTypeDescription
serverstringServer as configured or discovered
resolvedIPstring \null
resolvedFQDNstring \null
portintPort used
foreststringForest root DN
domainstringDomain this DC belongs to
isGCboolWhether this target was a Global Catalog
discoverySourcestringconfigured / gc_itself / gc_discovered
outcomestringOk / Partial / Failed
connectErrorstring \null
phaseErrorsdictphase_name → error string
certCountsdictPer-phase counts + total

Configuration reference

The sensor uses a forests: block. Each forest entry defines credentials shared by all domains inside it; any field can be overridden at the domain or gc_servers level. Full annotated example: DiscoveryManager/Sensors/discover_activedirectory/ConfigExample.yaml.

Minimal — one forest, one DC
Name:    ActiveDirectoryDiscovery
ExtName: Discover_ActiveDirectory
Config:
  scan_name: "corp-scan"
  page_size:  500
  forests:
    - name:       "corp.test.local"
      auth_type:  simple          # simple | ntlm | kerberos
      username:   "CORP\\Administrator"
      password:   "<secret>"
      use_ssl:    true
      verify_ssl: false
      domains:
        - server:  "dc01.corp.test.local"
          base_dn: "DC=corp,DC=test,DC=local"
Multi-forest — GC discovery + explicit DCs
Name:    ActiveDirectoryDiscovery
ExtName: Discover_ActiveDirectory
Config:
  scan_name:               "enterprise-scan"
  page_size:               500
  connect_timeout_seconds: 10
  search_timeout_seconds:  30
  retry_attempts:          3

  forests:

    - name:       "corp.test.local"
      auth_type:  ntlm
      domain:     "CORP"            # required for ntlm
      username:   "Administrator"
      password:   "<secret>"
      use_ssl:    true
      verify_ssl: false
      domains:
        - server:  "dc01.corp.test.local"
          base_dn: "DC=corp,DC=test,DC=local"

    - name:       "partner.local"
      auth_type:  ntlm
      domain:     "PARTNER"
      username:   "Administrator"
      password:   "<secret>"
      use_ssl:    true
      verify_ssl: false
      gc_servers:
        - server: "gc01.partner.local"    # GC auto-discovers all child/tree DCs
      domains:
        - server:  "gc01.partner.local"
          base_dn: "DC=partner,DC=local"
        - server:  "dc01.child.partner.local"
          base_dn: "DC=child,DC=partner,DC=local"
        - server:  "dc01.nestedchild.child.partner.local"
          base_dn: "DC=nestedchild,DC=child,DC=partner,DC=local"
        - server:  "dc01.mergedpartner.local"
          base_dn: "DC=mergedpartner,DC=local"
Skip a known-unreachable domain
domains:
  - server:  "dc01.isolated.corp.example.com"
    base_dn: "DC=isolated,DC=corp,DC=example,DC=com"
    skip:    true
Per-domain credential override
domains:
  - server:   "dc01.us.corp.example.com"
    base_dn:  "DC=us,DC=corp,DC=example,DC=com"
    username: "US\\Administrator"   # overrides forest-level credential
    password: "<secret>"

Known limitations

LimitationDetail
DNS for tree domainsTree domains (e.g. mergedpartner.local) require a conditional DNS forwarder on the parent-forest DC pointing at the tree DC's IP. Without it, hostname resolution fails with LDAPSocketOpenError.
verify_ssl: trueDC cert must be issued by a CA trusted by the scanning machine. Self-signed DC certs will fail. Use verify_ssl: false for internal AD.
NTLM auth — limited testingImplemented but not tested end-to-end. simple auth is the verified path.
DPAPI key bytescurrentValue (actual RSA blob) requires LSAD RPC — not over LDAP 636. Metadata only; keyBytesAccessible: false.
krbtgt key bytesNever exposed via LDAP. Only pwdLastSet and KVNO emitted.
GC requires port 636 reachableSecondary connection to port 636 is opened for CN=Partitions queries. Both 3269 and 636 must be open on the GC server.

Permanent out-of-scope

ItemReason
Certificate templatesBlueprints only — no keys. Classification is CBOM server's job.
AD CS archived private keysStored in the CA's JET database encrypted under the CA Exchange cert. certutil -getkey is the only extraction path — requires CA admin rights. Not accessible over LDAP and not extractable via wincerts (wincerts reads Windows cert store, not CA database). Needs a dedicated discover_adcs sensor.
EFS recovery agent certSYSVOL / SMB — not LDAP. Needs SMB sensor.
OCSP responder certsHTTP endpoints — HTTPS sensor.
NTLM hashesNever exposed via LDAP.
Computer machine passwordNT hash in NTDS.dit — never via LDAP.
Cert purpose classificationEKU OIDs emitted in sourceProperties — S/MIME / VPN / code-signing classification is CBOM server's job.

Python dependencies

ldap3           >= 2.9
cryptography    >= 41.0
jsonschema      >= 4.0

Remaining work

PriorityItemNotes
🔴 HighDuplicate discoverID bugSame object scanned twice can produce different UUIDs — downstream deduplication breaks.
🔴 HighNTLM auth end-to-end testImplemented but untested against a real DC. simple auth is the verified path.
🔴 HighProduction run with CBOM serverAll local testing passes. Need a real deposit → dedup → CryptoMaterial pipeline run against the CBOM server.
🟡 MediumSchema validation on all emitted docsOnly _ad_cert_to_doc validates against Schema.json currently. Key docs (secret_key, private_key, SSH, NGC) emit without schema check.
🟡 Medium_adfs.py unit tests in wincertsdiscover_wincerts/_adfs.py has no test coverage — PowerShell invocation + cert extraction path is untested.
🟢 Lowverify_ssl: true CA trust setupDocument how to add the DC's issuing CA cert to the scanning machine's trust store.
🟢 LowProxy supportNot implemented. Large enterprises may block direct LDAP 636.
🟢 LowConfiguration NC deeper scanAdditional objects under CN=Services,CN=Configuration not yet inventoried.
Completed
ItemDone
Split sensor into phase files✅ _phase_1_domain_certs.py … _phase_10_cross_certs.py, _helpers.py, _connection.py, _discovery.py
Lab seeding scripts✅ Seed-1-Minimal.ps1 (12-step, idempotent, multi-domain); Seed-2-Bulk.ps1 (10k scale)
Unit tests✅ 408 tests across 14 files in tests/discover_ad/
Config format refactor✅ New forests: block with per-domain override, GC discovery, skip flag
CRL revocation enrichment✅ Pre-fetched at scan start; isRevoked: true added to matching certs
TPM phase✅ _scan_tpm_keys — msTPM-InformationObject linked to computers
On this Page:
Support Privacy Policy Terms of Service

Copyright 2026 Encryption Consulting LLC. All rights reserved.