Public/Get-EFBaseline.ps1

function Get-EFBaseline {
    <#
    .SYNOPSIS
    Loads a built-in or file-based Windows computer checklist.
 
    .DESCRIPTION
    A checklist is a list of things expected to be true, such as Windows settings,
    required files, recent events, or an available network service. PowerShell commands
    call it a baseline for compatibility. This command only loads and validates the JSON
    file. It does not read a target file or event log, attempt a network connection, check
    a setting, or change a computer. ListAvailable shows the checklists included with the
    module.
 
    .PARAMETER Name
    The built-in checklist name. EnterpriseRecommended is the default.
 
    .PARAMETER Path
    The path to a custom checklist JSON file. Review custom files before use because they
    choose which local paths, event logs, hosts, and ports later checks can inspect.
 
    .PARAMETER ListAvailable
    Lists information about every checklist included with the installed module.
 
    .EXAMPLE
    Get-EFBaseline -Name EnterpriseRecommended
 
    .EXAMPLE
    Get-EFBaseline -Path .\contoso-baseline.json
 
    .EXAMPLE
    Get-EFBaseline -ListAvailable
 
    .EXAMPLE
    Get-EFBaseline -Path .\checklists\Contoso.EverydayChecks.json
 
    Loads and validates an everyday-checklist file without running any of its checks.
 
    .OUTPUTS
    EndpointForge.Baseline or EndpointForge.BaselineInfo.
 
    .LINK
    New-EFBaseline
 
    .LINK
    Test-EFBaseline
    #>

    [CmdletBinding(DefaultParameterSetName = 'Name')]
    param(
        [Parameter(ParameterSetName = 'Name')]
        [ValidateNotNullOrEmpty()]
        [string]$Name = 'EnterpriseRecommended',

        [Parameter(Mandatory, ParameterSetName = 'Path')]
        [ValidateNotNullOrEmpty()]
        [string]$Path,

        [Parameter(Mandatory, ParameterSetName = 'List')]
        [switch]$ListAvailable
    )

    if ($ListAvailable) {
        foreach ($file in Get-ChildItem -LiteralPath (Join-Path $script:ModuleRoot 'Data') -Filter '*.json' -File) {
            if ($file.Name -eq 'Baseline.schema.json') {
                continue
            }
            try {
                $item = Get-Content -LiteralPath $file.FullName -Raw -Encoding UTF8 | ConvertFrom-Json -ErrorAction Stop
                Assert-EFBaseline -Baseline $item
                [pscustomobject]@{
                    PSTypeName   = 'EndpointForge.BaselineInfo'
                    Name         = [string]$item.Name
                    Version      = [string]$item.Version
                    Description  = [string]$item.Description
                    ControlCount = @($item.Controls).Count
                    Path         = $file.FullName
                }
            }
            catch {
                Write-Warning "Skipping invalid built-in baseline '$($file.Name)': $($_.Exception.Message)"
            }
        }
        return
    }

    if ($PSCmdlet.ParameterSetName -eq 'Name') {
        if ($Name -notmatch '^[A-Za-z0-9._-]+$') {
            throw [System.ArgumentException]::new("Baseline name '$Name' contains invalid characters.")
        }
        $resolvedPath = Join-Path (Join-Path $script:ModuleRoot 'Data') "$Name.json"
        if (-not (Test-Path -LiteralPath $resolvedPath -PathType Leaf)) {
            throw [System.IO.FileNotFoundException]::new("Built-in baseline '$Name' was not found.")
        }
    }
    else {
        $resolvedPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path)
        if (-not (Test-Path -LiteralPath $resolvedPath -PathType Leaf)) {
            throw [System.IO.FileNotFoundException]::new("Baseline file '$resolvedPath' was not found.")
        }
    }

    try {
        $baseline = Get-Content -LiteralPath $resolvedPath -Raw -Encoding UTF8 | ConvertFrom-Json -ErrorAction Stop
    }
    catch {
        throw [System.IO.InvalidDataException]::new("Baseline '$resolvedPath' is not valid JSON: $($_.Exception.Message)")
    }

    Assert-EFBaseline -Baseline $baseline
    $baseline.PSObject.TypeNames.Insert(0, 'EndpointForge.Baseline')
    $baseline | Add-Member -NotePropertyName SourcePath -NotePropertyValue $resolvedPath -Force
    $baseline | Add-Member -NotePropertyName ControlCount -NotePropertyValue @($baseline.Controls).Count -Force
    $baseline | Add-Member -NotePropertyName RemediableCount -NotePropertyValue @($baseline.Controls | Where-Object Remediable).Count -Force
    return $baseline
}