Files
SecureBootCA2023/Invoke-SecureBootAudit.ps1
T
Petr Stepan 9a230866a2 Initial commit: detekční skript, remediační skript a README
- Invoke-SecureBootAudit.ps1: audit Secure Boot certifikátů (Fáze 1)
  - detekce prostředí (Physical/Hyper-V VM/VMware VM)
  - parsování EFI_SIGNATURE_LIST, detekce 2011/2023 certifikátů
  - registry stav, Event Log analýza, kategorizace, JSON výstup

- Set-SecureBootCertificateUpdate.ps1: remediace dle KB5068202
  - AvailableUpdates = 0x5944
  - scheduled task s wait smyčkou (timeout 120s)
  - WhatIf, Force, VerifyOnly, WinRM

- README.md: popis problému, detekce stavů, remediační postup
2026-06-05 14:05:27 +00:00

655 lines
26 KiB
PowerShell

#Requires -Version 5.1
<#
.SYNOPSIS
Audituje stav Secure Boot certifikátů na Windows Serveru.
.DESCRIPTION
Detekuje podporu Secure Boot, stav povolení, přítomnost certifikátů (expirující 2011
vs. nové 2023 náhrady), stav v registrech a relevantní záznamy v Event Logu.
Vrací strukturovaný JSON výstup + human-readable souhrn.
Skript nevyžaduje žádné externí moduly (pure PowerShell 5.1+).
Toleruje prostředí bez Secure Boot (Legacy BIOS, Gen1 VM apod.).
Spouštění na vzdáleném serveru:
Invoke-Command -ComputerName SERVER01 -FilePath .\Invoke-SecureBootAudit.ps1
Spouštění lokálně s uložením výsledku:
.\Invoke-SecureBootAudit.ps1 -OutputPath C:\Audit\result.json
.PARAMETER OutputPath
Cesta pro uložení JSON výsledku. Pokud není zadána, JSON se nevypisuje na konzoli
(použijte -JsonOnly nebo -PassThru pro programatické zpracování).
.PARAMETER JsonOnly
Vypíše pouze JSON na stdout, bez human-readable souhrnue.
.PARAMETER PassThru
Vrátí výsledek jako PowerShell objekt (vhodné pro Invoke-Command pipeline).
.EXAMPLE
.\Invoke-SecureBootAudit.ps1
.EXAMPLE
.\Invoke-SecureBootAudit.ps1 -OutputPath C:\Audit\SERVER01.json
.EXAMPLE
Invoke-Command -ComputerName SERVER01 -FilePath .\Invoke-SecureBootAudit.ps1 -ArgumentList $null,$false,$true
.NOTES
Vyžaduje spuštění jako Administrator pro přístup k UEFI databázím a Event Logu.
Relevantní KB: KB5062710, KB5068202, KB5085046
#>
[CmdletBinding()]
param(
[string]$OutputPath,
[switch]$JsonOnly,
[switch]$PassThru
)
$ErrorActionPreference = 'SilentlyContinue'
#region ── Helper functions ──────────────────────────────────────────────────
function Get-EnvironmentType {
try {
$cs = Get-WmiObject Win32_ComputerSystem -ErrorAction Stop
$mfr = [string]$cs.Manufacturer
$model = [string]$cs.Model
if ($mfr -like '*VMware*') { return 'VMware VM' }
if ($mfr -like '*Microsoft*' -and $model -eq 'Virtual Machine') { return 'Hyper-V VM' }
if ($model -like '*Virtual*' -or $mfr -like '*QEMU*' -or $mfr -like '*Xen*') {
return 'Other VM'
}
return 'Physical'
} catch {
return 'Unknown'
}
}
function Get-HardwareInfo {
$hw = [ordered]@{
Manufacturer = 'Unknown'
Model = 'Unknown'
SerialNumber = 'Unknown'
FirmwareType = 'Unknown'
BiosVersion = 'Unknown'
BiosReleaseDate = 'Unknown'
}
try {
$cs = Get-WmiObject Win32_ComputerSystem -ErrorAction Stop
$hw.Manufacturer = [string]$cs.Manufacturer
$hw.Model = [string]$cs.Model
} catch {}
try {
$bios = Get-WmiObject Win32_BIOS -ErrorAction Stop
$hw.BiosVersion = [string]$bios.SMBIOSBIOSVersion
$hw.SerialNumber = [string]$bios.SerialNumber
if ($bios.ReleaseDate) {
$hw.BiosReleaseDate = [Management.ManagementDateTimeConverter]::ToDateTime(
$bios.ReleaseDate).ToString('yyyy-MM-dd')
}
} catch {}
# Firmware type — primárně z registry, fallback přes přítomnost SecureBoot klíče
$fwTypeKey = Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control' `
-Name PEFirmwareType -ErrorAction SilentlyContinue
if ($fwTypeKey) {
$hw.FirmwareType = if ($fwTypeKey.PEFirmwareType -eq 2) { 'UEFI' } else { 'Legacy BIOS' }
} elseif (Test-Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot') {
$hw.FirmwareType = 'UEFI'
} else {
$hw.FirmwareType = 'Legacy BIOS'
}
return $hw
}
function Get-SecureBootState {
$state = [ordered]@{
IsUEFI = $false
IsSupported = $false
IsEnabled = $false
ConfirmResult = 'Unknown'
Error = $null
}
$fwTypeKey = Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control' `
-Name PEFirmwareType -ErrorAction SilentlyContinue
$state.IsUEFI = ($fwTypeKey -and $fwTypeKey.PEFirmwareType -eq 2) `
-or (Test-Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot')
if (-not $state.IsUEFI) { return $state }
try {
$result = Confirm-SecureBootUEFI -ErrorAction Stop
$state.IsSupported = $true
$state.IsEnabled = [bool]$result
$state.ConfirmResult = $result.ToString()
} catch {
$msg = $_.Exception.Message
if ($msg -like '*not supported*' -or $msg -like '*Cmdlet not supported*') {
$state.IsSupported = $false
$state.ConfirmResult = 'NotSupported'
} elseif ($msg -like '*disabled*') {
$state.IsSupported = $true
$state.IsEnabled = $false
$state.ConfirmResult = 'Disabled'
} else {
$state.IsSupported = $true
$state.IsEnabled = $false
$state.ConfirmResult = "Error"
$state.Error = $msg
}
}
return $state
}
function Parse-EFISignatureList {
<#
.SYNOPSIS
Parsuje EFI_SIGNATURE_LIST strukturu a vrátí X.509 certifikáty.
#>
param([byte[]]$Bytes)
$certs = @()
if (-not $Bytes -or $Bytes.Length -lt 28) { return $certs }
# EFI_CERT_X509_GUID {a5c059a1-94e4-4aa7-87b5-ab155c2bf072} v little-endian
$X509_GUID = [byte[]](
0xa1,0x59,0xc0,0xa5, # Data1 LE
0xe4,0x94, # Data2 LE
0xa7,0x4a, # Data3 LE
0x87,0xb5,0xab,0x15,0x5c,0x2b,0xf0,0x72 # Data4 BE
)
$offset = 0
while ($offset + 28 -le $Bytes.Length) {
$sigTypeGUID = $Bytes[$offset..($offset + 15)]
$sigListSize = [BitConverter]::ToUInt32($Bytes, $offset + 16)
$sigHeaderSize = [BitConverter]::ToUInt32($Bytes, $offset + 20)
$sigSize = [BitConverter]::ToUInt32($Bytes, $offset + 24)
if ($sigListSize -lt 28 -or $sigListSize -gt ($Bytes.Length - $offset)) { break }
# Porovnat GUID
$isX509 = $true
for ($i = 0; $i -lt 16; $i++) {
if ($sigTypeGUID[$i] -ne $X509_GUID[$i]) { $isX509 = $false; break }
}
if ($isX509 -and $sigSize -gt 16) {
$sigOffset = $offset + 28 + $sigHeaderSize
$listEnd = $offset + $sigListSize
while ($sigOffset + $sigSize -le $listEnd) {
# Přeskočit 16 B SignatureOwner GUID, zbytek je DER certifikát
$certOffset = $sigOffset + 16
$certSize = [int]$sigSize - 16
if ($certOffset + $certSize -le $Bytes.Length -and $certSize -gt 0) {
$certBytes = $Bytes[$certOffset..($certOffset + $certSize - 1)]
try {
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2(
, [byte[]]$certBytes)
$certs += $cert
} catch { }
}
$sigOffset += $sigSize
}
}
$offset += $sigListSize
}
return $certs
}
function Convert-CertToInfo {
param([System.Security.Cryptography.X509Certificates.X509Certificate2]$Cert)
return [ordered]@{
Subject = $Cert.Subject
Thumbprint = $Cert.Thumbprint
NotBefore = $Cert.NotBefore.ToString('yyyy-MM-dd')
NotAfter = $Cert.NotAfter.ToString('yyyy-MM-dd')
}
}
function Get-CertificateStatus {
$status = [ordered]@{
KEK = [ordered]@{
Has2011 = $false
Has2023 = $false
Certs2011 = @()
Certs2023 = @()
Error = $null
}
DB = [ordered]@{
Has2011UEFI = $false
Has2011WindowsPCA = $false
Has2023UEFI = $false
Has2023OptionROM = $false
Has2023WindowsUEFI = $false
Certs2011 = @()
Certs2023 = @()
Error = $null
}
AnyExpiring2011 = $false
AllReplacements2023 = $false
}
# ── KEK databáze ──
try {
$kekObj = Get-SecureBootUEFI -Name KEK -ErrorAction Stop
$kekCerts = Parse-EFISignatureList -Bytes $kekObj.Bytes
foreach ($cert in $kekCerts) {
$subj = $cert.Subject
$info = Convert-CertToInfo $cert
if ($subj -like '*KEK CA 2011*') {
$status.KEK.Has2011 = $true
$status.KEK.Certs2011 += $info
}
if ($subj -like '*KEK 2K CA 2023*' -or ($subj -like '*KEK*CA 2023*')) {
$status.KEK.Has2023 = $true
$status.KEK.Certs2023 += $info
}
}
} catch {
$status.KEK.Error = $_.Exception.Message
}
# ── DB databáze ──
try {
$dbObj = Get-SecureBootUEFI -Name db -ErrorAction Stop
$dbCerts = Parse-EFISignatureList -Bytes $dbObj.Bytes
foreach ($cert in $dbCerts) {
$subj = $cert.Subject
$info = Convert-CertToInfo $cert
# 2011 expirující certifikáty
if ($subj -like '*UEFI CA 2011*') {
$status.DB.Has2011UEFI = $true
$status.DB.Certs2011 += $info
}
if ($subj -like '*Windows Production PCA 2011*' -or $subj -like '*Windows PCA 2011*') {
$status.DB.Has2011WindowsPCA = $true
$status.DB.Certs2011 += $info
}
# 2023 náhradní certifikáty
if ($subj -like '*UEFI CA 2023*' -and
$subj -notlike '*Option ROM*' -and
$subj -notlike '*Windows UEFI*') {
$status.DB.Has2023UEFI = $true
$status.DB.Certs2023 += $info
}
if ($subj -like '*Option ROM UEFI CA 2023*') {
$status.DB.Has2023OptionROM = $true
$status.DB.Certs2023 += $info
}
if ($subj -like '*Windows UEFI CA 2023*') {
$status.DB.Has2023WindowsUEFI = $true
$status.DB.Certs2023 += $info
}
}
} catch {
$status.DB.Error = $_.Exception.Message
}
$status.AnyExpiring2011 = $status.KEK.Has2011 -or
$status.DB.Has2011UEFI -or
$status.DB.Has2011WindowsPCA
$status.AllReplacements2023 = $status.KEK.Has2023 -and
$status.DB.Has2023UEFI -and
$status.DB.Has2023OptionROM -and
$status.DB.Has2023WindowsUEFI
return $status
}
function Get-RegistryStatus {
$reg = [ordered]@{
SecureBootEnabled = $null
AvailableUpdates = $null
HighConfidenceOptOut = $null
ServicingKeyExists = $false
UEFICA2023Status = $null
UEFICA2023StatusText = 'KeyNotPresent'
UEFICA2023Error = $null
WindowsUEFICA2023Capable = $null
}
# Hlavní klíč
$mainProps = Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot' `
-ErrorAction SilentlyContinue
if ($mainProps) {
$reg.SecureBootEnabled = $mainProps.SecureBootEnabled
$reg.AvailableUpdates = $mainProps.AvailableUpdates
$reg.HighConfidenceOptOut = $mainProps.HighConfidenceOptOut
}
# Servicing podklíč
$svcProps = Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing' `
-ErrorAction SilentlyContinue
if ($svcProps) {
$reg.ServicingKeyExists = $true
$reg.UEFICA2023Status = $svcProps.UEFICA2023Status
$reg.UEFICA2023Error = $svcProps.UEFICA2023Error
$reg.WindowsUEFICA2023Capable = $svcProps.WindowsUEFICA2023Capable
$reg.UEFICA2023StatusText = switch ($reg.UEFICA2023Status) {
0 { 'NotStarted' }
1 { 'InProgress' }
2 { 'Success' }
3 { 'Failed' }
$null { 'KeyNotPresent' }
default { "Unknown ($($reg.UEFICA2023Status))" }
}
}
return $reg
}
function Get-EventLogStatus {
$evtStatus = [ordered]@{
LastEventId = $null
LastEventTime = $null
LastEventMessage = $null
ConfidenceLevel = 'NoRelevantEvents'
RelevantEvents = @()
Error = $null
}
$relevantIds = @(1795, 1796, 1800, 1801, 1802, 1803, 1808)
try {
$events = Get-WinEvent -FilterHashtable @{
LogName = 'System'
Id = $relevantIds
} -MaxEvents 20 -ErrorAction Stop
if ($events) {
$sorted = $events | Sort-Object TimeCreated -Descending
foreach ($evt in ($sorted | Select-Object -First 10)) {
$msgShort = ($evt.Message -replace '\s+', ' ').TrimStart()
$msgShort = if ($msgShort.Length -gt 250) { $msgShort.Substring(0, 250) + '...' } else { $msgShort }
$evtStatus.RelevantEvents += [ordered]@{
EventId = $evt.Id
TimeCreated = $evt.TimeCreated.ToString('yyyy-MM-dd HH:mm:ss')
Level = $evt.LevelDisplayName
Message = $msgShort
}
}
$last = $sorted | Select-Object -First 1
$evtStatus.LastEventId = $last.Id
$evtStatus.LastEventTime = $last.TimeCreated.ToString('yyyy-MM-dd HH:mm:ss')
$lastMsg = ($last.Message -replace '\s+', ' ').TrimStart()
$evtStatus.LastEventMessage = if ($lastMsg.Length -gt 300) {
$lastMsg.Substring(0, 300) + '...'
} else { $lastMsg }
$evtStatus.ConfidenceLevel = switch ($last.Id) {
1808 { 'HighConfidence-Success' }
1801 { 'HighConfidence-Failed' }
1795 { 'Failed-HyperVKnownIssue' }
1802 { 'Pending' }
1803 { 'InProgress' }
default { 'Informational' }
}
}
} catch {
$msg = $_.Exception.Message
if ($msg -like '*No events*' -or $_.CategoryInfo.Reason -eq 'NoMatchingEventsException') {
$evtStatus.ConfidenceLevel = 'NoRelevantEvents'
} else {
$evtStatus.Error = $msg
$evtStatus.ConfidenceLevel = 'EventLogError'
}
}
return $evtStatus
}
function Get-RemediationCategory {
param($Result)
$sb = $Result.SecureBoot
$cert = $Result.Certificates
$reg = $Result.Registry
$env = $Result.EnvironmentType
# Bez UEFI / Secure Boot není podporováno
if (-not $sb.IsUEFI -or -not $sb.IsSupported) {
if ($env -like '*VM*') {
return @{ Code = 'NO_SECUREBOOT_VM'; Emoji = '❌'; Label = 'Secure Boot nepodporováno (VM bez vTPM/UEFI)' }
}
return @{ Code = 'NO_SECUREBOOT'; Emoji = '❌'; Label = 'Secure Boot nepodporováno (Legacy BIOS)' }
}
if (-not $sb.IsEnabled) {
return @{ Code = 'SECUREBOOT_DISABLED'; Emoji = '⏸️'; Label = 'Secure Boot vypnuto' }
}
# Secure Boot je zapnutý — zkontrolovat certifikáty
if ($cert.AllReplacements2023 -and -not $cert.AnyExpiring2011) {
return @{ Code = 'OK'; Emoji = '✅'; Label = 'OK — má nové 2023 certifikáty' }
}
if ($cert.AllReplacements2023 -and $cert.AnyExpiring2011) {
return @{ Code = 'OK_TRANSITION'; Emoji = '✅'; Label = 'OK — přechodný stav (2023 i 2011 certifikáty)' }
}
# Selhání aktualizace
if ($reg.UEFICA2023Status -eq 3 -or
$Result.EventLog.LastEventId -eq 1795 -or
$Result.EventLog.LastEventId -eq 1801) {
return @{ Code = 'UPDATE_FAILED'; Emoji = '🔴'; Label = 'Selhání aktualizace certifikátů' }
}
# Aktualizace právě probíhá / čeká na restart
if ($reg.UEFICA2023Status -eq 1 -or $reg.UEFICA2023Status -eq 2) {
return @{ Code = 'UPDATE_PENDING'; Emoji = '⏳'; Label = 'Aktualizace dokončena, čeká na restart' }
}
# Firmware nepodporuje nové certifikáty
if ($null -ne $reg.WindowsUEFICA2023Capable -and $reg.WindowsUEFICA2023Capable -eq 0) {
return @{ Code = 'FIRMWARE_UPDATE_NEEDED'; Emoji = '🔧'; Label = 'Čeká na firmware update (OEM)' }
}
# Nutná aktualizace certifikátů
return @{ Code = 'UPDATE_NEEDED'; Emoji = '⚠️'; Label = 'Nutná aktualizace certifikátů' }
}
#endregion
#region ── Main ──────────────────────────────────────────────────────────────
$auditStart = Get-Date
# Předpočítat hodnoty, které by způsobily parse error uvnitř hashtable (try/catch v PS 5.1)
$_fqdn = try { [Net.Dns]::GetHostEntry('').HostName } catch { $env:COMPUTERNAME }
$_osInfo = Get-WmiObject Win32_OperatingSystem -ErrorAction SilentlyContinue
$_osCaption = if ($_osInfo) { $_osInfo.Caption } else { $null }
$_osBuild = if ($_osInfo) { $_osInfo.BuildNumber } else { $null }
$result = [ordered]@{
AuditTimestamp = $auditStart.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
Hostname = $env:COMPUTERNAME
FQDN = $_fqdn
OSCaption = $_osCaption
OSBuild = $_osBuild
Architecture = $env:PROCESSOR_ARCHITECTURE
EnvironmentType = Get-EnvironmentType
Hardware = Get-HardwareInfo
SecureBoot = Get-SecureBootState
Certificates = $null
Registry = Get-RegistryStatus
EventLog = Get-EventLogStatus
Category = $null
CategoryLabel = $null
RemediationAction = $null
}
# Certifikáty parsovat pouze pokud je Secure Boot dostupný
if ($result.SecureBoot.IsUEFI -and $result.SecureBoot.IsSupported) {
$result.Certificates = Get-CertificateStatus
} else {
$result.Certificates = [ordered]@{
KEK = [ordered]@{
Has2011 = $false; Has2023 = $false
Certs2011 = @(); Certs2023 = @()
Error = 'Secure Boot not available — certificate check skipped'
}
DB = [ordered]@{
Has2011UEFI = $false; Has2011WindowsPCA = $false
Has2023UEFI = $false; Has2023OptionROM = $false; Has2023WindowsUEFI = $false
Certs2011 = @(); Certs2023 = @()
Error = 'Secure Boot not available — certificate check skipped'
}
AnyExpiring2011 = $false
AllReplacements2023 = $false
}
}
# Kategorie
$cat = Get-RemediationCategory -Result $result
$result.Category = $cat.Code
$result.CategoryLabel = "$($cat.Emoji) $($cat.Label)"
$remediationMap = @{
'OK' = 'Žádná akce'
'OK_TRANSITION' = 'Žádná akce (monitorovat dokud nezmizí 2011 certifikáty)'
'UPDATE_NEEDED' = 'Naplánovat rollout nových certifikátů (KB5068202)'
'UPDATE_FAILED' = 'Troubleshooting selhání — zkontrolovat Event 1795/1801 (KB5085046)'
'UPDATE_PENDING' = 'Provést restart serveru pro dokončení aktualizace'
'FIRMWARE_UPDATE_NEEDED'= 'Kontaktovat OEM / aktualizovat firmware serveru'
'SECUREBOOT_DISABLED' = 'Rozhodnutí o zapnutí Secure Boot (mimo scope skriptu)'
'NO_SECUREBOOT' = 'Dokumentovat jako výjimku — Legacy BIOS, Secure Boot nelze'
'NO_SECUREBOOT_VM' = 'Dokumentovat jako výjimku — VM bez Secure Boot (Gen1 / bez vTPM)'
}
$result.RemediationAction = $remediationMap[$result.Category]
$result.AuditDurationMs = [int](Get-Date).Subtract($auditStart).TotalMilliseconds
#endregion
#region ── Output ────────────────────────────────────────────────────────────
$jsonOutput = $result | ConvertTo-Json -Depth 10
if ($OutputPath) {
$jsonOutput | Out-File -FilePath $OutputPath -Encoding UTF8 -Force
Write-Host "JSON uložen: $OutputPath" -ForegroundColor Green
}
if (-not $JsonOnly) {
$sb = $result.SecureBoot
$cert = $result.Certificates
$reg = $result.Registry
$evt = $result.EventLog
$hw = $result.Hardware
$catColor = switch -Wildcard ($result.Category) {
'OK*' { 'Green' }
'UPDATE_NEEDED' { 'Yellow' }
'UPDATE_PENDING' { 'Cyan' }
'UPDATE_FAILED' { 'Red' }
'FIRMWARE*' { 'Magenta' }
'SECUREBOOT_DISABLED' { 'Yellow' }
default { 'Gray' }
}
$line = '=' * 60
Write-Host ''
Write-Host $line -ForegroundColor Cyan
Write-Host " SECURE BOOT AUDIT — $($result.Hostname)" -ForegroundColor Cyan
Write-Host " $($result.AuditTimestamp)" -ForegroundColor DarkGray
Write-Host $line -ForegroundColor Cyan
Write-Host ''
Write-Host 'SERVER' -ForegroundColor Yellow
Write-Host " Hostname : $($result.Hostname)"
Write-Host " FQDN : $($result.FQDN)"
Write-Host " OS : $($result.OSCaption) (Build $($result.OSBuild))"
Write-Host " Prostředí : $($result.EnvironmentType)"
Write-Host " Hardware : $($hw.Manufacturer) $($hw.Model) [S/N: $($hw.SerialNumber)]"
Write-Host " BIOS/FW : $($hw.BiosVersion) ($($hw.BiosReleaseDate))"
Write-Host " Firmware typ: $($hw.FirmwareType)"
Write-Host ''
Write-Host 'SECURE BOOT' -ForegroundColor Yellow
Write-Host " UEFI firmware : $($sb.IsUEFI)"
Write-Host " Podporováno : $($sb.IsSupported)"
Write-Host " Povoleno : $($sb.IsEnabled)"
if ($sb.Error) { Write-Host " ! Chyba : $($sb.Error)" -ForegroundColor Red }
Write-Host ''
Write-Host 'CERTIFIKÁTY' -ForegroundColor Yellow
$c = $cert
Write-Host " ── Expirující 2011 ──────────────────────────────────"
Write-Host " KEK CA 2011 (exp. 24.6.2026) : $(if ($c.KEK.Has2011) {'PŘÍTOMEN ⚠️'} else {'chybí'})"
Write-Host " DB UEFI CA 2011 (exp. 27.6.2026): $(if ($c.DB.Has2011UEFI) {'PŘÍTOMEN ⚠️'} else {'chybí'})"
Write-Host " DB Windows PCA 2011 (19.10.2026) : $(if ($c.DB.Has2011WindowsPCA) {'PŘÍTOMEN ⚠️'} else {'chybí'})"
Write-Host " ── Nové náhrady 2023 ────────────────────────────────"
Write-Host " KEK 2K CA 2023 : $(if ($c.KEK.Has2023) {'přítomen ✓'} else {'CHYBÍ'})"
Write-Host " DB UEFI CA 2023 : $(if ($c.DB.Has2023UEFI) {'přítomen ✓'} else {'CHYBÍ'})"
Write-Host " DB Option ROM UEFI CA 2023 : $(if ($c.DB.Has2023OptionROM) {'přítomen ✓'} else {'CHYBÍ'})"
Write-Host " DB Windows UEFI CA 2023 : $(if ($c.DB.Has2023WindowsUEFI) {'přítomen ✓'} else {'CHYBÍ'})"
if ($c.KEK.Error) { Write-Host " ! KEK chyba : $($c.KEK.Error)" -ForegroundColor Red }
if ($c.DB.Error) { Write-Host " ! DB chyba : $($c.DB.Error)" -ForegroundColor Red }
Write-Host ''
Write-Host 'REGISTRY STAV' -ForegroundColor Yellow
Write-Host " UEFICA2023Status : $($reg.UEFICA2023Status) ($($reg.UEFICA2023StatusText))"
Write-Host " AvailableUpdates : $($reg.AvailableUpdates)"
Write-Host " WindowsUEFICA2023Capable: $($reg.WindowsUEFICA2023Capable)"
Write-Host " HighConfidenceOptOut : $($reg.HighConfidenceOptOut)"
if ($reg.UEFICA2023Error) {
Write-Host " ! UEFICA2023Error : $($reg.UEFICA2023Error)" -ForegroundColor Red
}
Write-Host ''
Write-Host 'EVENT LOG (relevantní EventID: 1795/1796/1800-1803/1808)' -ForegroundColor Yellow
Write-Host " Poslední event : EventID $($evt.LastEventId) ($($evt.LastEventTime))"
Write-Host " Confidence level : $($evt.ConfidenceLevel)"
if ($evt.RelevantEvents.Count -gt 0) {
Write-Host " Posledních $([Math]::Min($evt.RelevantEvents.Count,5)) záznamů:"
foreach ($e in ($evt.RelevantEvents | Select-Object -First 5)) {
$ec = if ($e.EventId -eq 1808) { 'Green' }
elseif ($e.EventId -in @(1795,1801)) { 'Red' }
else { 'DarkGray' }
Write-Host " [$($e.TimeCreated)] EventID $($e.EventId) $($e.Level)" -ForegroundColor $ec
}
} else {
Write-Host ' Žádné relevantní záznamy nenalezeny.' -ForegroundColor DarkGray
}
Write-Host ''
Write-Host 'VÝSLEDEK' -ForegroundColor Yellow
Write-Host " $($result.CategoryLabel)" -ForegroundColor $catColor
Write-Host " Doporučená akce: $($result.RemediationAction)" -ForegroundColor White
Write-Host ''
Write-Host $line -ForegroundColor Cyan
Write-Host ''
}
if ($JsonOnly) {
Write-Output $jsonOutput
}
if ($PassThru) {
return $result
}
#endregion