Private/Get/Get-AdcsObject.ps1

function Get-AdcsObject {
    <#
        .SYNOPSIS
        Retrieves all objects from the Public Key Services Container in Active Directory.
 
        .DESCRIPTION
        Queries the Active Directory Configuration partition to retrieve all objects from the
        Public Key Services Container (CN=Public Key Services,CN=Services,CN=Configuration).
        This container contains Certificate Authority objects, Certificate Templates, and other
        PKI-related objects used by Active Directory Certificate Services (AD CS).
         
        Uses module-level $script:Credential, $script:RootDSE, and $script:AdcsObjectStore
        variables set by Invoke-Locksmith2. The function performs a recursive LDAP search and
        returns LS2AdcsObject instances for all discovered PKI objects, including their
        properties and ACLs.
 
        .INPUTS
        None. This function does not accept pipeline input.
 
        .OUTPUTS
        LS2AdcsObject
        Returns LS2AdcsObject instances for all objects found in the Public Key Services
        container and its subtree.
 
        .EXAMPLE
        Get-AdcsObject
        Retrieves all AD CS objects using script-scope credentials and root DSE.
 
        .EXAMPLE
        $templates = Get-AdcsObject | Where-Object { $_.IsCertificateTemplate() }
        Retrieves all certificate template objects from the PKI container.
 
        .NOTES
        Requires script-scope variables set by Invoke-Locksmith2:
        - $script:Credential: Credentials for AD access
        - $script:RootDSE: Forest configuration naming context
        - $script:AdcsObjectStore: Cache of retrieved objects
 
        .LINK
        https://learn.microsoft.com/en-us/windows-server/identity/ad-cs/
    #>

    [CmdletBinding()]
    param ()

    #requires -Version 5.1 -Modules Microsoft.PowerShell.Security

    begin {
        # Initialize the AD CS Object Store if it doesn't exist
        if (-not $script:AdcsObjectStore) {
            $script:AdcsObjectStore = @{}
        }
    }

    process {
        try {
            # Build the LDAP search base for the Public Key Services container
            $searchBase = "CN=Public Key Services,CN=Services,$($script:RootDSE.configurationNamingContext)"
            
            Write-Verbose "Searching $searchBase for AD CS objects."
            Write-Verbose "AD CS Object Store currently has $($script:AdcsObjectStore.Count) entries"
            
            # Create DirectorySearcher for recursive search
            $searcherDirectoryEntry = New-AuthenticatedDirectoryEntry -Path "$($script:RootDSE.Parent)/$searchBase"
            $searcher = New-Object System.DirectoryServices.DirectorySearcher($searcherDirectoryEntry)
            $searcher.Filter = "(objectClass=*)"  # Get all objects
            $searcher.SearchScope = [System.DirectoryServices.SearchScope]::Subtree  # Recursive search
            $searcher.PageSize = 1000  # Handle large result sets
            
            # Get all results
            $searchResults = $searcher.FindAll()
            
            # Convert paths into DirectoryEntry objects and store them
            $objectCount = 0
            $cachedCount = 0
            $searchResults | ForEach-Object {
                $objectDirectoryEntry = $_.GetDirectoryEntry()
                $distinguishedName = $objectDirectoryEntry.distinguishedName.Value
                
                Write-Verbose "`nFound object: $distinguishedName`nClass: $($objectDirectoryEntry.objectClass -join ', ')"
                
                # Store the AD CS object if not already stored
                if (-not $script:AdcsObjectStore.ContainsKey($distinguishedName)) {
                    # Create LS2AdcsObject from DirectoryEntry
                    $adcsObject = [LS2AdcsObject]::new($objectDirectoryEntry)
                    
                    $script:AdcsObjectStore[$distinguishedName] = $adcsObject
                    $cachedCount++
                    Write-Verbose "Stored AD CS object: $distinguishedName"
                }
                
                $objectDirectoryEntry
                $objectCount++
            }
            Write-Verbose "Found $objectCount total objects in the Public Key Services container and its subtree"
            Write-Verbose "Stored $cachedCount new AD CS objects (Total store size: $($script:AdcsObjectStore.Count))"
            
            # Clean up
            $searcher.Dispose()
            $searcherDirectoryEntry.Dispose()
            $searchResults.Dispose()
        } catch {
            $errorRecord = [System.Management.Automation.ErrorRecord]::new(
                $_.Exception,
                'ADCSObjectRetrievalFailed',
                [System.Management.Automation.ErrorCategory]::NotSpecified,
                $searchBase
            )
            $PSCmdlet.WriteError($errorRecord)
        }
    }
}