Private/Interactive/Select-TBCatalogEntry.ps1
|
function Show-TBCatalogDetailView { <# .SYNOPSIS Renders a full-screen detail view for a single catalog category. .DESCRIPTION Displays category metadata, description, and all security checks with their recommended values. In arrow-key mode, uses ReadKey for Enter/Esc navigation. In classic mode, uses a Y/N confirmation prompt. .PARAMETER Category The catalog category object to display. .OUTPUTS [bool] $true if the user confirms, $false to go back. #> [CmdletBinding()] [OutputType([bool])] param( [Parameter(Mandatory = $true)] [PSCustomObject]$Category ) $tests = @($Category.Tests) $separator = ' ' + ('-' * 54) Write-Host '' Write-Host (' {0}' -f $Category.Name) -ForegroundColor Cyan Write-Host (' {0} | {1}' -f $Category.Framework, $Category.Severity) -ForegroundColor DarkGray Write-Host $separator -ForegroundColor DarkGray Write-Host '' Write-Host (' {0}' -f $Category.Description) -ForegroundColor White Write-Host '' Write-Host (' Security Checks ({0}):' -f $tests.Count) -ForegroundColor Cyan Write-Host '' foreach ($test in $tests) { $valueStr = $test.RecommendedValue if ($valueStr.Length -gt 30) { $valueStr = $valueStr.Substring(0, 27) + '...' } Write-Host (' {0} = {1}' -f $test.Property, $valueStr) -ForegroundColor White Write-Host (' {0}' -f $test.Description) -ForegroundColor DarkGray } Write-Host '' Write-Host $separator -ForegroundColor DarkGray if (Test-TBArrowKeySupport) { Write-Host '' Write-Host ' Press Enter to use this category, Esc to go back' -ForegroundColor DarkGray while ($true) { $key = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') if ($key.VirtualKeyCode -eq 13) { return $true } # Enter if ($key.VirtualKeyCode -eq 27) { return $false } # Escape } } else { $confirmed = Read-TBUserInput -Prompt 'Use this category?' -Confirm return $confirmed } } function Select-TBCatalogEntry { <# .SYNOPSIS Interactive two-level selection from the Maester baseline security catalog. .DESCRIPTION Groups catalog categories by Workload, lets the user pick a workload, then single-select a category with a detail view before confirming. Returns unique UTCM resource type name strings for the confirmed category. #> [CmdletBinding()] [OutputType([string[]])] param() $catalog = Get-TBBaselineCatalog $categories = @($catalog.Categories) # Group categories by Workload $workloads = [ordered]@{} foreach ($cat in $categories) { $wl = $cat.Workload if (-not $workloads.Contains($wl)) { $workloads[$wl] = @() } $workloads[$wl] += $cat } # Step 1: Show workload selection $workloadNames = @($workloads.Keys) $workloadOptions = foreach ($wl in $workloadNames) { $count = @($workloads[$wl]).Count '{0} ({1} monitors)' -f $wl, $count } $wlChoice = Show-TBMenu -Title 'Security Catalog - Select Workload' -Options $workloadOptions -IncludeBack if ($wlChoice -eq 'Back') { return $null } $selectedWorkload = $workloadNames[$wlChoice] $workloadCategories = @($workloads[$selectedWorkload]) # Step 2: Category browsing loop (single-select with detail view) $categoryOptions = foreach ($cat in $workloadCategories) { $testCount = @($cat.Tests).Count '{0} [{1}] -- {2} checks' -f $cat.Name, $cat.Severity, $testCount } $arrowMode = Test-TBArrowKeySupport while ($true) { if ($arrowMode) { Clear-Host Write-Host '' Write-Host ' -- Create from Maester --' -ForegroundColor Cyan Write-Host '' } $catChoice = Show-TBMenu -Title ('{0} - Select Category' -f $selectedWorkload) -Options $categoryOptions -IncludeBack if ($catChoice -eq 'Back') { return $null } $selectedCategory = $workloadCategories[$catChoice] if ($arrowMode) { Clear-Host Write-Host '' Write-Host ' -- Create from Maester --' -ForegroundColor Cyan } $confirmed = Show-TBCatalogDetailView -Category $selectedCategory if ($confirmed) { $allTypes = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase) foreach ($rt in $selectedCategory.ResourceTypes) { $null = $allTypes.Add($rt) } if ($allTypes.Count -eq 0) { return $null } $testCount = @($selectedCategory.Tests).Count Write-Host '' Write-Host (' Selected "{0}" covering {1} resource type(s) and {2} security check(s):' -f $selectedCategory.Name, $allTypes.Count, $testCount) -ForegroundColor Green foreach ($typeName in $allTypes) { Write-Host (' - {0}' -f $typeName) -ForegroundColor White } Write-Host '' return @($allTypes) } # If not confirmed, loop back to category menu } } |