Data di pubblicazione originale: 17 novembre 2025
ID KB: 5072718
|
Modifica data |
Modificare la descrizione |
|
24 febbraio 2026 |
|
|
22 febbraio 2026 |
|
|
13 febbraio 2026 |
|
Script di esempio per la raccolta dei dati dell'inventario di avvio protetto
Copiare e incollare questo script di esempio e modificarlo in base alle esigenze per l'ambiente: script di raccolta dati di esempio per l'inventario di avvio protetto.
<# . SINOSSI Rileva lo stato di aggiornamento del certificato di avvio protetto per il monitoraggio a livello di flotta.
. DESCRIZIONE Questo script di rilevamento raccoglie lo stato di avvio protetto, i valori del Registro di sistema per l'aggiornamento dei certificati, e informazioni sul dispositivo. Restituisce una stringa JSON per il monitoraggio e la creazione di report.
Compatibile con Intune Correzioni, raccolta basata su Oggetto Criteri di gruppo e altri strumenti di gestione.Non è necessario alcun script di correzione: questa operazione viene eseguita solo per il monitoraggio.
Exit 0 = "Without issue" (certificati aggiornati) Exit 1 = "With issue" (certificates not updated — informational only)
. PARAMETER OutputPath Opzionale. Percorso di una cartella in cui verrà salvato il file JSON.Se disponibile, salva HOSTNAME_latest.json in questa cartella.Se non viene fornito, viene generato JSON su stdout (comportamento originale).
. ESEMPIO # Output in stdout (rilevamento Intune/SCCM) \Detect-SecureBootCertUpdateStatus.ps1
. ESEMPIO # Save to network share (GPO deployment) .\Detect-SecureBootCertUpdateStatus.ps1 -OutputPath "\\server\SecureBootLogs$"
. NOTE Percorsi del Registro di sistema per https://aka.ms/securebootplaybook: HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing
IL SOFTWARE VIENE FORNITO "COSÌ COME È", SENZA GARANZIE DI ALCUN TIPO, EXPRESS O IMPLICITE, COMPRESE, TRA LE ALTRE, LE GARANZIE DI COMMERCIABILITÀ, IDONEITÀ PER UNO SCOPO SPECIFICO E NON VIOLAZIONE DI DIRITTI DI PROPRIETÀ. IN NESSUN CASO LA AUTORI O PROPRIETARI DEL COPYRIGHT SARANNO RITENUTI RESPONSABILI PER QUALSIASI RIVENDICAZIONE, DANNO O ALTRO RESPONSABILITÀ, SIA NELL'ESERCIZIO DEL CONTRATTO, CHE PER ILLECITO CIVILE O ALTRA AZIONE CIVILE, DERIVANTI DA IN CONNESSIONE CON IL SOFTWARE O CON L'USO O ALTRE ATTIVITÀ RELATIVE A SOFTWARE.#> param( [Parametro(Obbligatorio = $false)] [stringa]$OutputPath )
# URL di download: https://aka.ms/getsecureboot -> "Esempi di distribuzione e monitoraggio" # Nota: questo script viene eseguito sugli endpoint per raccogliere i dati di stato di avvio protetto.
# 1. Hostname # PS Version: All | Amministrazione: No | Requisiti di sistema: Nessuno prova { $hostname = $env:NOMECOMPUTER if ([string]::IsNullOrEmpty($hostname)) { Write-Warning "Impossibile determinare hostname" $hostname = "Sconosciuto" } Write-Host "Hostname: $hostname" } catch { Write-Warning "Errore durante il recupero di hostname: $_" $hostname = "Errore" Write-Host "Hostname: $hostname" }
# 2. CollectionTime # PS Version: All | Amministrazione: No | Requisiti di sistema: Nessuno prova { $collectionTime = Get-Date if ($null -eq $collectionTime) { Write-Warning "Impossibile recuperare la data/ora corrente" $collectionTime = "Sconosciuto" } Write-Host "Tempo di raccolta: $collectionTime" } catch { Write-Warning "Errore durante il recupero di data/ora: $_" $collectionTime = "Errore" Write-Host "Tempo di raccolta: $collectionTime" }
# Registro di sistema: chiave principale di avvio protetto (3 valori)
# 3. SecureBootEnabled # VERSIONE PS: 3.0+ | Amministrazione: può essere richiesto | Requisiti di sistema: sistema che supporta UEFI/Avvio protetto prova { $secureBootEnabled = Confirm-SecureBootUEFI -ErrorAction Stop Write-Host "Avvio protetto abilitato: $secureBootEnabled" } catch { Write-Warning "Impossibile determinare lo stato di avvio protetto tramite cmdlet: $_" # Prova il fallback del Registro di sistema prova { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\State" -Name UEFISecureBootEnabled -ErrorAction Stop $secureBootEnabled = [bool]$regValue.UEFISecureBootEnabled Write-Host "Avvio protetto abilitato: $secureBootEnabled" } catch { Write-Warning "Impossibile determinare lo stato di avvio protetto tramite il Registro di sistema. Il sistema potrebbe non supportare UEFI/Avvio protetto". $secureBootEnabled = $null Write-Host "Avvio protetto abilitato: non disponibile" } }
# 4. HighConfidenceOptOut # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name HighConfidenceOptOut -ErrorAction Stop $highConfidenceOptOut = $regValue.HighConfidenceOptOut Write-Host "Rifiuto esplicito con confidenza elevata: $highConfidenceOptOut" } catch { # HighConfidenceOptOut è facoltativo e non è presente nella maggior parte dei sistemi $highConfidenceOptOut = $null Write-Host "Rifiuto esplicito con confidenza elevata: non impostato" }
N. 4b. MicrosoftUpdateManagedOptIn # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name MicrosoftUpdateManagedOptIn -ErrorAction Stop $microsoftUpdateManagedOptIn = $regValue.MicrosoftUpdateManagedOptIn Write-Host "Consenso esplicito gestito da Microsoft Update: $microsoftUpdateManagedOptIn" } catch { # MicrosoftUpdateManagedOptIn è facoltativo, non presente nella maggior parte dei sistemi $microsoftUpdateManagedOptIn = $null Write-Host "Consenso esplicito gestito da Microsoft Update: non impostato" }
# 5. AvailableUpdates # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name AvailableUpdates -ErrorAction Stop $availableUpdates = $regValue.AvailableUpdates if ($null -ne $availableUpdates) { # Converti in formato esadecimale $availableUpdatesHex = "0x{0:X}" -f $availableUpdates Write-Host "Aggiornamenti disponibile: $availableUpdatesHex" } else { Write-Host "Disponibile Aggiornamenti: Non disponibile" } } catch { Write-Warning "AvailableUpdates registry key not found or inaccessible" $availableUpdates = $null Write-Host "Disponibile Aggiornamenti: Non disponibile" }
N. 5b. AvailableUpdatesPolicy (valore permanente controllato dall'oggetto Criteri di gruppo) # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name AvailableUpdatesPolicy -ErrorAction Stop $availableUpdatesPolicy = $regValue.AvailableUpdatesPolicy if ($null -ne $availableUpdatesPolicy) { # Converti in formato esadecimale $availableUpdatesPolicyHex = "0x{0:X}" -f $availableUpdatesPolicy Write-Host "Criteri di Aggiornamenti disponibili: $availableUpdatesPolicyHex" } else { Write-Host "Criterio di Aggiornamenti disponibile: non impostato" } } catch { # AvailableUpdatesPolicy è facoltativo: impostato solo quando viene applicato l'oggetto Criteri di gruppo $availableUpdatesPolicy = $null Write-Host "Criterio di Aggiornamenti disponibile: non impostato" }
# Registro di sistema: chiave di manutenzione (3 valori)
# 6. UEFICA2023Status # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023Status -ErrorAction Stop $uefica 2023Status = $regValue.UEFICA2023Status Write-Host "Stato DELLA UEFI di Windows 2023: $uefica 2023Status" } catch { Write-Warning "Chiave del Registro di sistema di stato DI WINDOWS UEFI 2023 non trovata o non accessibile" $uefica 2023Status = $null Write-Host "Stato DELLA UEFI di Windows 2023: non disponibile" }
# 7. UEFICA2023Errore # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023Error -ErrorAction Stop $uefica 2023Error = $regValue.UEFICA2023Error Write-Host "Errore UEFI CA 2023: $uefica 2023Errore" } catch { # UEFICA2023Errore esiste solo se si è verificato un errore: assenza buona $uefica 2023Error = $null Write-Host "Errore UEFI CA 2023: Nessuno" }
# 8. UEFICA2023ErrorEvent # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023ErrorEvent -ErrorAction Stop $uefica 2023ErrorEvent = $regValue.UEFICA2023ErrorEvent Write-Host "Evento errore UEFI CA 2023: $uefica 2023ErrorEvent" } catch { $uefica 2023ErrorEvent = $null Write-Host "Evento di errore UEFI CA 2023: non disponibile" }
# Registro di sistema: Attributi del dispositivo (7 valori: 9-15)
# 9. OEMManufacturerName # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OEMManufacturerName -ErrorAction Stop $oemManufacturerName = $regValue.OEMManufacturerName if ([string]::IsNullOrEmpty($oemManufacturerName)) { Write-Warning "OEMManufacturerName è vuoto" $oemManufacturerName = "Sconosciuto" } Write-Host "Nome produttore OEM: $oemManufacturerName" } catch { Write-Warning "OEMManufacturerName chiave del Registro di sistema non trovata o non accessibile" $oemManufacturerName = $null Write-Host "Nome produttore OEM: non disponibile" }
# 10. OEMModelSystemFamily # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OEMModelSystemFamily -ErrorAction Stop $oemModelSystemFamily = $regValue.OEMModelSystemFamily if ([string]::IsNullOrEmpty($oemModelSystemFamily)) { Write-Warning "OEMModelSystemFamily è vuoto" $oemModelSystemFamily = "Sconosciuto" } Write-Host "Famiglia di sistemi MODELLO OEM: $oemModelSystemFamily" } catch { Write-Warning "Chiave del Registro di sistema OEMModelSystemFamily non trovata o inaccessibile" $oemModelSystemFamily = $null Write-Host "Famiglia di sistemi modello OEM: non disponibile" }
# 11. OEMModelNumber # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OEMModelNumber -ErrorAction Stop $oemModelNumber = $regValue.OEMModelNumber if ([string]::IsNullOrEmpty($oemModelNumber)) { Write-Warning "OEMModelNumber is empty" $oemModelNumber = "Sconosciuto" } Write-Host "Numero modello OEM: $oemModelNumber" } catch { Write-Warning "CHIAVE OEMModelNumber del Registro di sistema non trovata o non accessibile" $oemModelNumber = $null Write-Host "Numero modello OEM: Non disponibile" }
# 12. FirmwareVersion # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name FirmwareVersion -ErrorAction Stop $firmwareVersion = $regValue.FirmwareVersion if ([string]::IsNullOrEmpty($firmwareVersion)) { Write-Warning "FirmwareVersion is empty" $firmwareVersion = "Sconosciuto" } Write-Host "Versione firmware: $firmwareVersion" } catch { Write-Warning "FirmwareVersion registry key not found or inaccessible" $firmwareVersion = $null Write-Host "Versione firmware: Non disponibile" }
# 13. FirmwareReleaseDate # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name FirmwareReleaseDate -ErrorAction Stop $firmwareReleaseDate = $regValue.FirmwareReleaseDate if ([string]::IsNullOrEmpty($firmwareReleaseDate)) { Write-Warning "FirmwareReleaseDate is empty" $firmwareReleaseDate = "Sconosciuto" } Write-Host "Data di rilascio del firmware: $firmwareReleaseDate" } catch { Write-Warning "FirmwareReleaseDate registry key not found or inaccessible" $firmwareReleaseDate = $null Write-Host "Data di rilascio del firmware: non disponibile" }
# 14. OSArchitecture # PS Version: All | Amministrazione: No | Requisiti di sistema: Nessuno prova { $osArchitecture = $env:PROCESSOR_ARCHITECTURE if ([string]::IsNullOrEmpty($osArchitecture)) { # Prova il fallback del Registro di sistema $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OSArchitecture -ErrorAction Stop $osArchitecture = $regValue.OSArchitecture } if ([string]::IsNullOrEmpty($osArchitecture)) { Write-Warning "Impossibile determinare OSArchitecture" $osArchitecture = "Sconosciuto" } Write-Host "Architettura del sistema operativo: $osArchitecture" } catch { Write-Warning "Errore durante il recupero dell'architettura OS: $_" $osArchitecture = "Sconosciuto" Write-Host "Architettura del sistema operativo: $osArchitecture" }
# 15. CanAttemptUpdateAfter (FILETIME) # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name CanAttemptUpdateAfter -ErrorAction Stop $canAttemptUpdateAfter = $regValue.CanAttemptUpdateAfter # Convert FILETIME to UTC DateTime : archivia il Registro di sistema come REG_BINARY (byte[]) o REG_QWORD (long) if ($null -ne $canAttemptUpdateAfter) { prova { if ($canAttemptUpdateAfter -is [byte[]]) { $fileTime = [BitConverter]::ToInt64($canAttemptUpdateAfter, 0) $canAttemptUpdateAfter = [DateTime]::FromFileTime($fileTime). ToUniversalTime() } elseif ($canAttemptUpdateAfter -is [long]) { $canAttemptUpdateAfter = [DateTime]::FromFileTime($canAttemptUpdateAfter). ToUniversalTime() } } catch { Write-Warning "Impossibile convertire CanAttemptUpdateAfter FILETIME in DateTime" } } Write-Host "Può tentare l'aggiornamento dopo: $canAttemptUpdateAfter" } catch { Write-Warning "CanAttemptUpdateDopo chiave del Registro di sistema non trovata o inaccessibile" $canAttemptUpdateAfter = $null Write-Host "Può tentare l'aggiornamento dopo: Non disponibile" }
# Registri eventi: Registro di sistema (10 valori: 16-25)
# 16-25. Query del registro eventi # ID evento: # 1801 - Aggiornamento avviato, riavvio richiesto N. 1808 - Aggiornamento completato # 1795 - Errore firmware restituito (codice di errore di acquisizione) # 1796 - Errore registrato con codice di errore (codice di acquisizione) # 1800 - Riavvio necessario (NON un errore - l'aggiornamento procederà dopo il riavvio) # 1802 - Aggiornamento bloccato del firmware noto (cattura KI_<numero> da SkipReason) # 1803 - Aggiornamento KEK corrispondente non trovato (OEM deve fornire KEK firmato PK) # VERSIONE PS: 3.0+ | Amministrazione: potrebbe essere necessario per il registro di sistema | Requisiti di sistema: Nessuno prova { # Esegui una query su tutti gli ID evento di avvio protetto pertinenti $allEventIds = @(1795, 1796, 1800, 1801, 1802, 1803, 1808) $events = @(Get-WinEvent -FilterHashtable @{LogName='System'; ID=$allEventIds} -MaxEvents 50 -ErrorAction Stop)
se ($events. Conteggio -eq 0) { Write-Warning "Nessun evento di avvio protetto trovato nel registro di sistema" $latestEventId = $null $bucketId = $null $confidence = $null $skipReasonKnownIssue = $null $event 1801Count = 0 $event 1808Count = 0 $event 1795Count = 0 $event 1795ErrorCode = $null $event 1796Count = 0 $event 1796ErrorCode = $null $event 1800Count = 0 $rebootPending = $false $event 1802Count = 0 $knownIssueId = $null $event 1803Count = 0 $missingKEK = $false Write-Host "ID evento più recente: Non disponibile" Write-Host "ID contenitore: non disponibile" Write-Host "Confidenza: non disponibile" Write-Host "Numero evento 1801: 0" Write-Host "Numero evento 1808: 0" } else { # 16. LatestEventId $latestEvent = $events | Sort-Object TempoCreato -Decrescente | Select-Object -Primo 1 if ($null -eq $latestEvent) { Write-Warning "Impossibile determinare l'evento più recente" $latestEventId = $null Write-Host "ID evento più recente: Non disponibile" } else { $latestEventId = $latestEvent.Id Write-Host "ID evento più recente: $latestEventId" }
# 17. BucketID - Estratto dall'evento 1801/1808 if ($null -ne $latestEvent -and $null -ne $latestEvent.Message) { if ($latestEvent.Message -match 'BucketId:\s*(.+)') { $bucketId = $matches[1]. Trim() Write-Host "ID bucket: $bucketId" } else { Write-Warning "BucketId non trovato nel messaggio dell'evento" $bucketId = $null Write-Host "ID bucket: non trovato nell'evento" } } else { Write-Warning "L'evento o il messaggio più recente è Null, non è possibile estrarre BucketId" $bucketId = $null Write-Host "ID bucket: non disponibile" }
# 18. Confidenza - Estratto dall'evento 1801/1808 if ($null -ne $latestEvent -and $null -ne $latestEvent.Message) { if ($latestEvent.Message -match 'BucketConfidenceLevel:\s*(.+)') { $confidence = $matches[1]. Trim() Write-Host "Confidenza: $confidence" } else { Write-Warning "Livello di probabilità non trovato nel messaggio dell'evento" $confidence = $null Write-Host "Confidenza: non trovato nell'evento" } } else { Write-Warning "L'evento o il messaggio più recente è Null, non è possibile estrarre confidenza" $confidence = $null Write-Host "Confidenza: non disponibile" }
N. 18b. SkipReason - Estrarre KI_<numero> da SkipReason nello stesso evento di BucketId # In questo modo vengono acquisiti gli ID dei problemi noti visualizzati insieme a BucketId/Confidence (non solo evento 1802) $skipReasonKnownIssue = $null if ($null -ne $latestEvent -and $null -ne $latestEvent.Message) { if ($latestEvent.Message -match 'SkipReason:\s*(KI_\d+)') { $skipReasonKnownIssue = $matches[1] Write-Host "SkipReason Known Issue: $skipReasonKnownIssue" -ForegroundColor Yellow } }
# 19. Event1801Count $event 1801Array = @($events | Where-Object {$_. Id -eq 1801}) $event 1801Count = $event 1801Array.Count Write-Host "Numero evento 1801: $event 1801Count"
# 20. Event1808Count $event 1808Array = @($events | Where-Object {$_. Id -eq 1808}) $event 1808Count = $event 1808Array.Count Write-Host "Numero evento 1808: $event 1808Count" # Inizializza variabili evento di errore $event 1795Count = 0 $event 1795ErrorCode = $null $event 1796Count = 0 $event 1796CodiceErrore = $null $event 1800Count = 0 $rebootPending = $false $event 1802Count = 0 $knownIssueId = $null $event 1803Count = 0 $missingKEK = $false # Controlla la presenza di eventi di errore solo se l'aggiornamento NON è stato completato # Ignora l'analisi degli errori se: 1808 è l'evento più recente O UEFICA2023Status è "Aggiornato" $updateComplete = ($latestEventId -eq 1808) -or ($uefica 2023Status -eq "Updated") if (-$updateComplete) { Write-Host "Aggiornamento non completato - controllo degli eventi di errore..." -ForegroundColor yellow # 21. Evento1795 - Errore firmware (codice di errore di acquisizione) $event 1795Array = @($events | Where-Object {$_. Id -eq 1795}) $event 1795Count = $event 1795Array.Count if ($event 1795Count -gt 0) { $latestEvent 1795 = $event 1795Array | Sort-Object TempoCreato -Decrescente | Select-Object -Primo 1 if ($latestEvent 1795.Message -match '(?:error|code|status)[:\s]*(?:0x)?( [0-9A-Fa-f]{8}|[0-9A-Fa-f]+)') { $event 1795ErrorCode = $matches[1] } Write-Host "Evento 1795 (errore firmware) Numero: $event 1795Count" $(if ($event 1795ErrorCode) { "Codice: $event 1795ErrorCode" }) } # 22. Evento1796 - Codice di errore registrato (codice di errore di acquisizione) $event 1796Array = @($events | Where-Object {$_. Id -eq 1796}) $event 1796Count = $event 1796Array.Count if ($event 1796Count -gt 0) { $latestEvent 1796 = $event 1796Array | Sort-Object TempoCreato -Decrescente | Select-Object -Primo 1 if ($latestEvent 1796.Message -match '(?:error|code|status)[:\s]*(?:0x)?( [0-9A-Fa-f]{8}|[0-9A-Fa-f]+)') { $event 1796CodiceErrore = $matches[1] } Write-Host "Evento 1796 (errore registrato) Conteggio: $event 1796Count" $(if ($event 1796ErrorCode) { "Code: $event 1796ErrorCode" }) } # 23. Evento1800 - Riavvio necessario (NON un errore - l'aggiornamento procederà dopo il riavvio) $event 1800Array = @($events | Where-Object {$_. Id -eq 1800}) $event 1800Count = $event 1800Array.Count $rebootPending = $event 1800Count -gt 0 if ($rebootPending) { Write-Host "Evento 1800 (riavvio in sospeso): l'aggiornamento verrà eseguito dopo il riavvio" -ForegroundColor Ciano } # 24. Evento1802 - Problema firmware noto (acquisizione di KI_<numero> da SkipReason) $event 1802Array = @($events | Where-Object {$_. Id -eq 1802}) $event 1802Count = $event 1802Array.Count if ($event 1802Count -gt 0) { $latestEvent 1802 = $event 1802Array | Sort-Object TempoCreato -Decrescente | Select-Object -Primo 1 if ($latestEvent 1802.Message -match 'SkipReason:\s*(KI_\d+)') { $knownIssueId = $matches[1] } Write-Host "Evento 1802 (problema firmware noto) Numero: $event 1802Count" $(if ($knownIssueId) { "KI: $knownIssueId" }) } # 25. Evento1803 - Aggiornamento KEK mancante (OEM deve fornire KEK firmato PK) $event 1803Array = @($events | Where-Object {$_. Id -eq 1803}) $event 1803Count = $event 1803Array.Count $missingKEK = $event 1803Count -gt 0 if ($missingKEK) { Write-Host "Evento 1803 (KEK mancante): OEM deve fornire KEK firmato PK" -ForegroundColor Giallo } } else { Write-Host "Aggiornamento completato (evento 1808 o Stato=Aggiornato) - analisi degli errori ignorata" -ForegroundColor verde } } } catch { Write-Warning "Errore durante il recupero dei registri eventi. Può richiedere privilegi di amministratore: $_" $latestEventId = $null $bucketId = $null $confidence = $null $skipReasonKnownIssue = $null $event 1801Count = 0 $event 1808Count = 0 $event 1795Count = 0 $event 1795ErrorCode = $null $event 1796Count = 0 $event 1796ErrorCode = $null $event 1800Count = 0 $rebootPending = $false $event 1802Count = 0 $knownIssueId = $null $event 1803Count = 0 $missingKEK = $false Write-Host "ID evento più recente: errore" Write-Host "ID bucket: errore" Write-Host "Confidenza: errore" Write-Host "Numero evento 1801: 0" Write-Host "Numero evento 1808: 0" }
# Query WMI/CIM (5 valori)
# 26. OSVersion # Versione PS: 3.0+ (usare Get-WmiObject per 2.0) | Amministrazione: No | Requisiti di sistema: Nessuno prova { $osInfo = Get-CimInstance Win32_OperatingSystem -ErrorAction Stop if ($null -eq $osInfo -or [string]::IsNullOrEmpty($osInfo.Version)) { Write-Warning "Impossibile recuperare la versione del sistema operativo" $osVersion = "Sconosciuto" } else { $osVersion = $osInfo.Version } Write-Host "Versione del sistema operativo: $osVersion" } catch { # CIM may fail in some environments - use fallback $osVersion = [System.Environment]::OSVersion.Version.ToString() if ([string]::IsNullOrEmpty($osVersion)) { $osVersion = "Unknown" } Write-Host "Versione del sistema operativo: $osVersion" }
# 27. LastBootTime # Versione PS: 3.0+ (usare Get-WmiObject per 2.0) | Amministrazione: No | Requisiti di sistema: Nessuno prova { $osInfo = Get-CimInstance Win32_OperatingSystem -ErrorAction Stop if ($null -eq $osInfo -o $null -eq $osInfo.LastBootUpTime) { Write-Warning "Impossibile recuperare l'ora dell'ultimo avvio" $lastBootTime = $null Write-Host "Ora ultimo avvio: non disponibile" } else { $lastBootTime = $osInfo.LastBootUpTime Write-Host "Ora ultimo avvio: $lastBootTime" } } catch { # CIM may fail in some environments - use fallback prova { $lastBootTime = (Get-Process -Id 0 -ErrorAction SilentlyContinue). Starttime } catch { $lastBootTime = $null } if ($lastBootTime) { Write-Host "Ora ultimo avvio: $lastBootTime" } else { Write-Host "Ora ultimo avvio: Non disponibile" } }
# 28. BaseBoardManufacturer # Versione PS: 3.0+ (usare Get-WmiObject per 2.0) | Amministrazione: No | Requisiti di sistema: Nessuno prova { $baseBoard = Get-CimInstance Win32_BaseBoard -ErrorAction Stop if ($null -eq $baseBoard -or [string]::IsNullOrEmpty($baseBoard.Manufacturer)) { Write-Warning "Impossibile recuperare il produttore della lavagna" $baseBoardManufacturer = "Sconosciuto" } else { $baseBoardManufacturer = $baseBoard.Manufacturer } Write-Host "Produttore lavagna: $baseBoardManufacturer" } catch { # CIM può non riuscire - le informazioni della scheda base sono supplementari $baseBoardManufacturer = "Sconosciuto" Write-Host "Produttore lavagna: $baseBoardManufacturer" }
# 29. BaseBoardProduct # Versione PS: 3.0+ (usare Get-WmiObject per 2.0) | Amministrazione: No | Requisiti di sistema: Nessuno prova { $baseBoard = Get-CimInstance Win32_BaseBoard -ErrorAction Stop if ($null -eq $baseBoard -or [string]::IsNullOrEmpty($baseBoard.Product)) { Write-Warning "Impossibile recuperare il prodotto baseboard" $baseBoardProduct = "Sconosciuto" } else { $baseBoardProduct = $baseBoard.Prodotto } Write-Host "Prodotto Baseboard: $baseBoardProduct" } catch { # CIM può non riuscire - le informazioni della scheda base sono supplementari $baseBoardProduct = "Sconosciuto" Write-Host "Prodotto Baseboard: $baseBoardProduct" }
# 30. SecureBootTaskEnabled # PS Version: All | Amministrazione: No | Requisiti di sistema: esiste un'attività programmata # Controlla se l'attività pianificata Secure-Boot-Update è abilitata $secureBootTaskEnabled = $null $secureBootTaskStatus = "Sconosciuto" prova { $taskOutput = schtasks.exe /Query /TN "\Microsoft\Windows\PI\Secure-Boot-Update" /FO CSV 2>&1 if ($LASTEXITCODE -eq 0) { $taskData = $taskOutput | ConvertFrom-Csv if ($taskData) { $secureBootTaskStatus = $taskData.Status $secureBootTaskEnabled = ($taskData.Status -eq 'Pronto' -o $taskData.Status -eq 'In esecuzione') } } else { $secureBootTaskStatus = "NotFound" $secureBootTaskEnabled = $false } if ($secureBootTaskEnabled -eq $false) { Write-Host "Attività di aggiornamento SecureBoot: $secureBootTaskStatus (abilitato: $secureBootTaskEnabled)" -ForegroundColor yellow } else { Write-Host "Attività di aggiornamento SecureBoot: $secureBootTaskStatus (abilitato: $secureBootTaskEnabled)" -ForegroundColor green } } catch { $secureBootTaskStatus = "Errore" $secureBootTaskEnabled = $false Write-Host "Attività di aggiornamento SecureBoot: controllo degli errori - $_" -ForegroundColor red }
# 31. Stato chiave WinCS (F33E0C8E002 - Aggiornamento del certificato di avvio protetto) # PS Version: All | Amministrazione: Sì (per la query) | Requisiti di sistema: WinCsFlags.exe $wincsKeyApplied = $null $wincsKeyStatus = "Sconosciuto" prova { # Controlla le posizioni comuni per WinCsFlags.exe $wincsFlagsPath = $null $possiblePaths = @( "$env:SystemRoot\System32\WinCsFlags.exe", "$env:SystemRoot\SysWOW64\WinCsFlags.exe" ) foreach ($p in $possiblePaths) { if (test-path $p) { $wincsFlagsPath = $p; break } } if ($wincsFlagsPath) { # Chiave specifica della query: richiede i diritti di amministratore $queryOutput = & $wincsFlagsPath /query --key F33E0C8E002 2>&1 $queryOutputStr = $queryOutput -join "'n" if ($LASTEXITCODE -eq 0) { # Controlla se la chiave è applicata (cerca "Configurazione attiva" o indicatore simile) if ($queryOutputStr -match "Active Configuration.*:.enabled" -or $queryOutputStr -match "Configuration.*applied") { $wincsKeyApplied = $true $wincsKeyStatus = "Applicato" Write-Host "Tasto WinCS F33E0C8E002: applicato" -Primo pianoColore verde } elseif ($queryOutputStr -match "non trovato|Nessuna configurazione") { $wincsKeyApplied = $false $wincsKeyStatus = "NotApplied" Write-Host "Tasto WinCS F33E0C8E002: non applicato" -Primo pianoColore giallo } else { # Key exists - check output for state $wincsKeyApplied = $true $wincsKeyStatus = "Applicato" Write-Host "Tasto WinCS F33E0C8E002: applicato" -Primo pianoColore verde } } else { # Verificare la presenza di messaggi di errore specifici if ($queryOutputStr -match "Accesso negato|amministratore") { $wincsKeyStatus = "AccessDenied" Write-Host "Tasto WinCS F33E0C8E002: accesso negato (eseguito come amministratore)" -ForegroundColor DarkGray } elseif ($queryOutputStr -match "non trovato|Nessuna configurazione") { $wincsKeyApplied = $false $wincsKeyStatus = "NotApplied" Write-Host "Tasto WinCS F33E0C8E002: non applicato" -Primo pianoColore giallo } else { $wincsKeyStatus = "QueryFailed" Write-Host "Tasto WinCS F33E0C8E002: query non riuscita" -ForegroundColor red } } } else { $wincsKeyStatus = "WinCsFlagsNotFound" Write-Host "Tasto WinCS F33E0C8E002: WinCsFlags.exe non trovato" -ForegroundColor gray } } catch { $wincsKeyStatus = "Errore" Write-Host "WinCS Key F33E0C8E002: Error checking - $_" -ForegroundColor Red }
# ============================================================================= # Remediation Detection - Output di stato & codice di uscita # =============================================================================
# Build status object from all collected inventory data $status = [ordered]@{ UEFICA2023Status = $uefica 2023Status UEFICA2023Error = $uefica 2023Error UEFICA2023ErrorEvent = $uefica 2023ErrorEvent AvailableUpdates = if ($null -ne $availableUpdates) { $availableUpdatesHex } else { $null } AvailableUpdatesPolicy = if ($null -ne $availableUpdatesPolicy) { $availableUpdatesPolicyHex } else { $null } Hostname = $hostname CollectionTime = if ($collectionTime -is [datetime]) { $collectionTime.ToString("o") } else { "$collectionTime" } SecureBootEnabled = $secureBootEnabled HighConfidenceOptOut = $highConfidenceOptOut MicrosoftUpdateManagedOptIn = $microsoftUpdateManagedOptIn OEMManufacturerName = $oemManufacturerName OEMModelSystemFamily = $oemModelSystemFamily OEMModelNumber = $oemModelNumber FirmwareVersion = $firmwareVersion FirmwareReleaseDate = $firmwareReleaseDate OSArchitecture = $osArchitecture CanAttemptUpdateAfter = if ($canAttemptUpdateAfter -is [datetime]) { $canAttemptUpdateAfter.ToString("o") } else { "$canAttemptUpdateAfter" } LatestEventId = $latestEventId BucketId = $bucketId Confidenza = $confidence SkipReasonKnownIssue = $skipReasonKnownIssue # KI_<numero> da SkipReason nell'evento BucketId Event1801Count = $event 1801Count Event1808Count = $event 1808Count # Eventi di errore con dettagli acquisiti Event1795Count = $event 1795Count # Errore firmware restituito Event1795ErrorCode = $event 1795ErrorCode # Codice di errore dal firmware Event1796Count = $event 1796Count # Codice di errore registrato Event1796ErrorCode = $event 1796ErrorCode # Codice di errore acquisito Event1800Count = $event 1800Count # Riavvio necessario (NON un errore) RebootPending = $rebootPending # True se è presente l'evento 1800 Event1802Count = $event 1802Count # Problema noto del firmware KnownIssueId = $knownIssueId # KI_<numero> da SkipReason Event1803Count = $event 1803Count # Aggiornamento KEK mancante MissingKEK = $missingKEK # OEM deve fornire KEK firmato PK OSVersion = $osVersion LastBootTime = if ($lastBootTime -is [datetime]) { $lastBootTime.ToString("o") } else { "$lastBootTime" } BaseBoardManufacturer = $baseBoardManufacturer BaseBoardProduct = $baseBoardProduct SecureBootTaskEnabled = $secureBootTaskEnabled SecureBootTaskStatus = $secureBootTaskStatus WinCSKeyApplied = $wincsKeyApplied # True se è applicato F33E0C8E002 chiave WinCSKeyStatus = $wincsKeyStatus # Applied, NotApplied, WinCsFlagsNotFound e così via. }
# Output dello stato - Per l'aggregazione dei dati $jsonOutput = $status | ConvertTo-Json -Comprimi
# Se OutputPath è stato fornito, salva nel file; in caso contrario output a stdout if (-not [string]::IsNullOrEmpty($OutputPath)) { # Convalida OutputPath: ignora se ha un aspetto simile a una richiesta di assistenza o ha caratteri non validi if ($OutputPath -match '^[/\-]' -o $OutputPath -match '[<>:"|? *]') { Write-Host "OutputPath specificato non valido, output in stdout" -ForegroundColor Yellow Write-Output $jsonOutput if ($secureBootEnabled -and $uefica 2023Status -eq "Updated") { exit 0 } else { exit 1 } } # Verificare che la cartella di output esista if (-not (Test-Path $OutputPath)) { prova { New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null } catch { Write-Warning "Impossibile creare la cartella di output: $OutputPath - $_" } } # Salva in HOSTNAME_latest.json $outputFile = Join-Path $OutputPath "$($hostname)_latest.json" prova { $jsonOutput | Out-File -FilePath $outputFile -Encoding UTF8 -Force Write-Host "JSON saved to: $outputFile" -ForegroundColor Green } catch { Write-Warning "Impossibile scrivere nel file: $outputFile - $_" # Torna a stdout Write-Output $jsonOutput } } else { # Comportamento originale - output a stdout Write-Output $jsonOutput }
# Codice di uscita: "Aggiornato" è il valore di successo per il playbook if ($secureBootEnabled -and $uefica 2023Status -eq "Updated") { exit 0 # Without issue } else { exit 1 # With issue }