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:

  1. Identity extraction – Retrieves the template's cn (common name) and displayName using the safe_ldap_attr helper to handle missing attributes gracefully (lines 29-31).
  2. Attribute normalization – Collects every LDAP attribute, preserving raw values while passing them through parse_attribute to convert binary or specialized formats into Python-native types (lines 34-38).
  3. Property derivation – Invokes analyze_template_properties to decode low-level flag integers into boolean security properties like Auto_Enrollment or Exportable_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:

Summary

  • The enumerate_templates function performs targeted LDAP subtree searches to discover Active Directory Certificate Templates.
  • It constructs the search base targeting CN=Certificate Templates and filters for pKICertificateTemplate object class.
  • Raw LDAP attributes are normalized through parse_attribute and safely extracted via safe_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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →