Private/Set/Set-CADisableExtensionList.ps1
|
function Set-CADisableExtensionList { <# .SYNOPSIS Queries and stores the Disable Extension List configuration for each Certification Authority. .DESCRIPTION This function queries the DisableExtensionList registry value for each CA using PSCertutil's Get-PCDisableExtensionList cmdlet. The DisableExtensionList indicates which certificate extensions are disabled on the CA, which is relevant for ESC16 detection (disabled CRL/AIA extensions). The function updates the AdcsObjectStore with: - DisableExtensionList: Array of disabled extension OIDs - SecurityExtensionDisabled: Boolean indicating if the security extension (1.3.6.1.4.1.311.25.2) is disabled .PARAMETER InputObject Pipeline input from previous Set-CA* functions. Must contain DistinguishedName and CAFullName properties. .OUTPUTS PSCustomObject with DistinguishedName and CAFullName properties for pipeline continuation. .EXAMPLE Set-CAComputerPrincipal | Set-CAInterfaceFlags | Set-CAEditFlags | Set-CAAuditFilter | Set-CADisableExtensionList .NOTES Requires PSCertutil module with Get-PCDisableExtensionList cmdlet. Part of the CA configuration pipeline in Invoke-Locksmith2. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [System.DirectoryServices.DirectoryEntry[]]$AdcsObject ) begin { Write-Verbose "Querying DisableExtensionList for Certification Authorities..." # Verify PSCertutil is available if (-not (Get-Command -Name Get-PCDisableExtensionList -ErrorAction SilentlyContinue)) { Write-Error "Get-PCDisableExtensionList cmdlet not found. Please ensure PSCertutil module is loaded." return } } process { $AdcsObject | Where-Object SchemaClassName -eq pKIEnrollmentService | ForEach-Object { try { # Extract CA name for logging $caName = if ($_.Properties -and $_.Properties.Contains('cn')) { $_.Properties['cn'][0] } elseif ($_.cn) { $_.cn } else { 'Unknown CA' } Write-Verbose "Processing CA: $caName" # Extract the DN from the DirectoryEntry $dn = if ($_.Properties -and $_.Properties.Contains('distinguishedName')) { $_.Properties['distinguishedName'][0] } elseif ($_.distinguishedName) { $_.distinguishedName } else { Write-Warning "Could not extract DistinguishedName for CA: $caName" $_ return } # Get the CAFullName from the AdcsObjectStore if (-not $script:AdcsObjectStore.ContainsKey($dn)) { Write-Warning "CA '$dn' not found in AD CS Object Store" $_ return } $caFullName = $script:AdcsObjectStore[$dn].CAFullName if ([string]::IsNullOrEmpty($caFullName)) { Write-Warning "CAFullName is empty for CA: $dn" $_ return } Write-Verbose " Querying DisableExtensionList for: $caFullName" # Query DisableExtensionList using PSCertutil $disableExtensionListResult = Get-PCDisableExtensionList -CAFullName $caFullName -ErrorAction Stop # Get-PCDisableExtensionList returns an array of objects with DisabledExtension property # or $null if no extensions are disabled # Force array wrapping with @() for PS 5.1 compatibility (.Count on single objects) if ($disableExtensionListResult -and @($disableExtensionListResult).Count -gt 0) { # Extract the extension OIDs/names into an array $disabledExtensions = $disableExtensionListResult | ForEach-Object { $_.DisabledExtension } Write-Verbose " Retrieved $($disabledExtensions.Count) disabled extension(s): $($disabledExtensions -join ', ')" # Check if the Microsoft Certificate Template Information extension is disabled # OID: 1.3.6.1.4.1.311.25.2 (szOID_CERTIFICATE_TEMPLATE) $securityExtensionDisabled = $disabledExtensions -contains '1.3.6.1.4.1.311.25.2' if ($securityExtensionDisabled) { Write-Verbose " CRITICAL: Security extension (1.3.6.1.4.1.311.25.2) is DISABLED" } else { Write-Verbose " Security extension (1.3.6.1.4.1.311.25.2) is enabled" } # Update the AD CS Object Store if ($script:AdcsObjectStore.ContainsKey($dn)) { $script:AdcsObjectStore[$dn].DisableExtensionList = $disabledExtensions $script:AdcsObjectStore[$dn].SecurityExtensionDisabled = $securityExtensionDisabled Write-Verbose " Updated AD CS Object Store for $dn with DisableExtensionList and SecurityExtensionDisabled" } } else { # No extensions disabled - store empty array and false Write-Verbose " No extensions disabled on this CA" if ($script:AdcsObjectStore.ContainsKey($dn)) { $script:AdcsObjectStore[$dn].DisableExtensionList = @() $script:AdcsObjectStore[$dn].SecurityExtensionDisabled = $false Write-Verbose " Updated AD CS Object Store for $dn with empty DisableExtensionList" } } } catch { Write-Verbose " Failed to query DisableExtensionList for '$caFullName': $($_.Exception.Message)" # Set to null on error if ($script:AdcsObjectStore.ContainsKey($dn)) { $script:AdcsObjectStore[$dn].DisableExtensionList = $null $script:AdcsObjectStore[$dn].SecurityExtensionDisabled = $null } } # Always return the object to continue the pipeline $_ } } end { Write-Verbose "Completed DisableExtensionList queries for all CAs" } } |