Private/Initialize/Initialize-PrincipalDefinitions.ps1

function Initialize-PrincipalDefinitions {
    <#
        .SYNOPSIS
        Loads and customizes principal definitions for the current forest.
 
        .DESCRIPTION
        Loads PrincipalDefinitions.psd1 and injects forest-specific security principals
        (such as the forest's Enterprise Admins SID) into the definitions. Stores the
        customized definitions in module-level variables for use throughout the scan.
         
        This function should be called after Initialize-DomainStore so that domain SIDs
        are available for injection.
 
        .INPUTS
        None
        Uses module-level variables $script:DomainStore and $script:RootDSE.
 
        .OUTPUTS
        None
        Populates module-level variables:
        - $script:SafePrincipals
        - $script:DangerousPrincipals
        - $script:StandardOwners
 
        .EXAMPLE
        Initialize-PrincipalDefinitions
        Loads principal definitions and customizes them for the current forest.
 
        .NOTES
        Requires $script:DomainStore and $script:RootDSE to be initialized first.
        The StandardOwners array will include the forest-specific Enterprise Admins SID.
    #>

    [CmdletBinding()]
    param()

    #requires -Version 5.1

    begin {
        Write-Verbose "Loading and customizing principal definitions..."
    }

    process {
        try {
            # Load the base definitions from PSD1 file
            # Use $PSScriptRoot which points to Private\Initialize, so go up one level to Private, then into Data
            $definitionsPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'Data\PrincipalDefinitions.psd1'
            Write-Verbose "Loading principal definitions from: $definitionsPath"
            
            if (-not (Test-Path $definitionsPath)) {
                throw "Principal definitions file not found at: $definitionsPath"
            }
            
            $definitions = Import-PowerShellDataFile -Path $definitionsPath
            Write-Verbose "Successfully loaded principal definitions file"
            
            # Start with the base definitions
            $script:SafePrincipals = $definitions.SafePrincipals
            $script:DangerousPrincipals = $definitions.DangerousPrincipals
            $script:StandardOwners = $definitions.StandardOwners
            
            # Inject forest-specific principals
            if ($script:RootDSE -and $script:DomainStore) {
                $rootDomainDN = $script:RootDSE.rootDomainNamingContext.Value
                
                if ($script:DomainStore.ContainsKey($rootDomainDN)) {
                    $forestRootDomain = $script:DomainStore[$rootDomainDN]
                    
                    if ($forestRootDomain.objectSid) {
                        # Add forest-specific Enterprise Admins SID
                        $enterpriseAdminsSid = "$($forestRootDomain.objectSid)-519"
                        
                        # Add to StandardOwners if not already present (avoid duplicates)
                        if ($enterpriseAdminsSid -notin $script:StandardOwners) {
                            $script:StandardOwners += $enterpriseAdminsSid
                            Write-Verbose "Added forest Enterprise Admins SID to StandardOwners: $enterpriseAdminsSid"
                        }
                    } else {
                        Write-Warning "Forest root domain SID not available in DomainStore"
                    }
                } else {
                    Write-Warning "Forest root domain not found in DomainStore"
                }
            } else {
                Write-Warning "DomainStore or RootDSE not initialized. Principal definitions will not include forest-specific SIDs."
            }
            
            Write-Verbose "Principal definitions loaded:"
            Write-Verbose " - Safe Principals: $($script:SafePrincipals.Count)"
            Write-Verbose " - Dangerous Principals: $($script:DangerousPrincipals.Count)"
            Write-Verbose " - Standard Owners: $($script:StandardOwners.Count)"
            
        } catch {
            Write-Warning "Failed to load principal definitions: $_"
            
            # Initialize with empty arrays as fallback
            if (-not $script:SafePrincipals) { $script:SafePrincipals = @() }
            if (-not $script:DangerousPrincipals) { $script:DangerousPrincipals = @() }
            if (-not $script:StandardOwners) { $script:StandardOwners = @() }
        }
    }
}