Understanding the enumerate_templates Function in Doom: AD Certificate Template Discovery
The enumerate_templates function in Doom performs targeted LDAP subtree searches to discover Active Directory Certificate Templates, parsing raw LDAP attributes into enriched, human-readable property dictionaries for security auditing.
Active Directory Certificate Services (AD CS) exposes certificate templates via LDAP, but raw directory entries contain opaque flag values and binary attributes. The Doom open-source tool abstracts this complexity through the enumerate_templates function, which queries the directory, normalizes attribute values, and derives high-level security properties. This article examines the implementation in src/doom/modules/enumerate_templates.py and explains how the function transforms raw LDAP data into actionable intelligence.
What Does the enumerate_templates Function Do?
The enumerate_templates function serves as the discovery engine for AD certificate templates. It executes a targeted LDAP search and processes the results into structured Python dictionaries.
The function begins by constructing the distinguished name (DN) for the Certificate Templates container, typically CN=Certificate Templates,<base_dn>. It then issues an LDAP subtree search for objects of class pKICertificateTemplate (lines 5-7 in src/doom/modules/enumerate_templates.py).
When the search returns entries, the function iterates through ldap_connection.entries and performs three critical transformations:
- Identity extraction – Retrieves the template's
cn(common name) anddisplayNameusing thesafe_ldap_attrhelper to handle missing attributes gracefully (lines 29-31). - Attribute normalization – Collects every LDAP attribute, preserving raw values while passing them through
parse_attributeto convert binary or specialized formats into Python-native types (lines 34-38). - Property derivation – Invokes
analyze_template_propertiesto decode low-level flag integers into boolean security properties likeAuto_EnrollmentorExportable_Key(lines 39-42).
The final output is a list of dictionaries, each containing name, display_name, dn, attributes, and the original LDAP entry object for advanced use.
Key Implementation Details in enumerate_templates
LDAP Search Scope and Object Filtering
The function targets a specific container within Active Directory. It constructs the search base by appending to the provided base_dn:
# Conceptual representation based on source lines 5-7
search_base = f"CN=Certificate Templates,{base_dn}"
search_filter = "(objectClass=pKICertificateTemplate)"
This ensures the query only returns certificate template objects, ignoring other directory entries.
Safe Attribute Extraction with safe_ldap_attr
Working with LDAP entries requires handling potentially missing or malformed attributes. The function utilizes safe_ldap_attr from src/doom/protocols/ldap.py to safely retrieve values:
# Lines 29-31 reference
name = safe_ldap_attr(entry, 'cn')
display_name = safe_ldap_attr(entry, 'displayName')
This helper prevents KeyError exceptions when attributes are absent, returning None or empty strings instead.
Parsing Raw LDAP Values
Raw LDAP attributes often contain binary data, distinguished names, or specialized formats. The parse_attribute function (located in src/doom/parsers/attribute.py) handles conversion to Python-native types:
# Lines 34-38 reference
for attr in entry.entry_attributes:
raw_value = entry[attr].value
parsed_value = parse_attribute(attr, raw_value)
attributes[attr] = parsed_value
This normalization step ensures downstream modules receive consistent data types regardless of LDAP schema variations.
Property Analysis and Flag Conversion
Certificate templates store security-relevant settings as bit flags in attributes like msPKI-Certificate-Name-Flag and pKIExtendedKeyUsage. The analyze_template_properties helper decodes these into human-readable booleans:
# Lines 39-42 reference
properties = analyze_template_properties(attributes)
attributes.update(properties)
This produces flags such as:
- Auto_Enrollment: Whether the template allows automatic certificate enrollment
- Exportable_Key: Whether the private key can be exported
- Client_Authentication: Whether the template supports client authentication EKUs
Practical Usage Example
The following example demonstrates how to invoke enumerate_templates within the Doom framework:
from doom.protocols.ldap import get_ldap_connection
from doom.modules.enumerate_templates import enumerate_templates
# 1️⃣ Establish an LDAP connection (example uses default credentials)
ldap_conn, base_dn = get_ldap_connection()
# 2️⃣ Retrieve all certificate templates
templates = enumerate_templates(ldap_conn, base_dn)
# 3️⃣ Iterate and display useful info
for tmpl in templates:
print(f"Template: {tmpl['display_name']} ({tmpl['name']})")
print(f" DN: {tmpl['dn']}")
print(" Properties:")
for prop, value in tmpl['attributes'].items():
# Show only the boolean flag properties
if isinstance(value, bool):
print(f" {prop}: {value}")
print("-" * 40)
This script connects to Active Directory, retrieves all certificate templates, and prints the derived security properties for each template.
Source Code Architecture
The enumerate_templates function relies on several supporting modules within the Doom codebase:
src/doom/modules/enumerate_templates.py– Implementsenumerate_templatesand theanalyze_template_propertieshelper that decodes certificate template flags.src/doom/protocols/ldap.py– Provides thesafe_ldap_attrhelper and LDAP connection utilities used to safely extract attribute values.src/doom/parsers/attribute.py– Containsparse_attribute, which translates raw LDAP values into Python-native types.src/doom/__main__.py– Entry point of the Doom tool where template enumeration can be triggered from the command line interface.
Summary
- The
enumerate_templatesfunction performs targeted LDAP subtree searches to discover Active Directory Certificate Templates. - It constructs the search base targeting
CN=Certificate Templatesand filters forpKICertificateTemplateobject class. - Raw LDAP attributes are normalized through
parse_attributeand safely extracted viasafe_ldap_attr. - The function derives high-level security properties by analyzing bit flags through
analyze_template_properties. - Output includes structured dictionaries with names, distinguished names, and enriched attribute sets suitable for security auditing.
Frequently Asked Questions
What LDAP object class does enumerate_templates search for?
The function searches for objects of class pKICertificateTemplate. It constructs an LDAP filter targeting this specific object class within the CN=Certificate Templates container to ensure only certificate template definitions are returned.
How does enumerate_templates handle malformed LDAP attributes?
The function utilizes the safe_ldap_attr helper from src/doom/protocols/ldap.py to safely retrieve attribute values. This helper prevents KeyError exceptions by returning None or empty strings when attributes are missing or malformed, ensuring the enumeration continues without crashing.
What properties are derived from the raw certificate template flags?
The analyze_template_properties helper decodes low-level bit flags into boolean properties such as Auto_Enrollment (indicating automatic certificate enrollment capability), Exportable_Key (indicating if private keys can be exported), and Client_Authentication (indicating Extended Key Usage support for client authentication).
Where is the enumerate_templates function located in the Doom repository?
The function is implemented in src/doom/modules/enumerate_templates.py. It is imported and utilized by the main entry point in src/doom/__main__.py and depends on helper functions defined in src/doom/protocols/ldap.py and src/doom/parsers/attribute.py.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →