BELANGRIJK Dit artikel met dit voorbeeldscript is buiten gebruik gesteld. Vanaf de Windows-updates die zijn uitgebracht op en na 12 mei 2026, bevindt het voorbeeldscript zich in de map %systemroot%\SecureBoot\ExampleRolloutScripts op uw apparaat.
Kopieer en plak dit voorbeeldscript en wijzig deze indien nodig voor uw omgeving:
<# . SYNOPSIS Implementeert de Secure Boot Rollout Orchestrator als een geplande Windows-taak.
.DESCRIPTION Hiermee maakt u een geplande taak waarmee de orchestrator continu op de achtergrond wordt uitgevoerd.De taak wordt uitgevoerd met het uitvoeringsbeleid voor overslaan, zodat er geen beveiligingsprompts worden weergegeven. De orchestrator zal het volgende doen: - Poll naar apparaatupdates op het opgegeven interval - Automatisch golven genereren en GPO's implementeren - Doorgaan totdat alle in aanmerking komende apparaten zijn bijgewerkt Voortgang bewaken met behulp van: Get-SecureBootRolloutStatus.ps1
.PARAMETER AggregationInputPath UNC-pad naar JSON-apparaatgegevens (van detectie-GPO)
.PARAMETER ReportBasePath Lokaal pad voor rapporten en statusbestanden
.PARAMETER TargetOU Organisatie-eenheid om groepsbeleidsobjecten te koppelen (optioneel- standaardinstelling voor domeinhoofdmap)
.PARAMETER PollIntervalMinutes Minuten tussen statuscontroles. Standaardwaarde: 30
.PARAMETER UseWinCS Gebruik WinCS (Windows Configuration System) in plaats van AvailableUpdatesPolicy GPO.Indien ingeschakeld, implementeert WinCsFlags.exe geplande taak naar eindpunten in plaats van register-GPO.
.PARAMETER WinCSKey De WinCS-sleutel voor de configuratie van beveiligd opstarten. Standaardinstelling: F33E0C8E002
.PARAMETER ServiceAccount Account om de taak uit te voeren. Standaardinstelling: SYSTEM Gebruik voor domeinbewerkingen een domeinbeheerdersserviceaccount.
.PARAMETER AllowListPath Pad naar een bestand met hostnamen naar ALLOW voor implementatie (gerichte/pilot-implementatie).Ondersteunt .txt (één hostnaam per regel) of .csv (met de kolom Hostname/ComputerName/Name).Wanneer dit is opgegeven, worden ALLEEN deze apparaten opgenomen in de implementatie.
.PARAMETER AllowADGroup Naam van een AD-beveiligingsgroep die computeraccounts bevat die moeten worden TOEGESTAAN.Voorbeeld: "SecureBoot-Pilot-Computers"
.PARAMETER ExclusionListPath Pad naar een bestand met hostnamen om UIT te sluiten van implementatie (VIP-/executive-apparaten).Ondersteunt .txt (één hostnaam per regel) of .csv (met de kolom Hostname/ComputerName/Name).
.PARAMETER ExcludeADGroup Naam van een AD-beveiligingsgroep met computeraccounts die moeten worden uitgesloten.Voorbeeld: "VIP-Computers"
.PARAMETER ScriptPath Pad naar het orchestratorscript. Standaard: dezelfde map als dit script.
.PARAMETER Uninstall De geplande taak verwijderen
.EXAMPLE .\Deploy-OrchestratorTask.ps1 -AggregationInputPath "\\server\SecureBootData$" -ReportBasePath "C:\SecureBootReports" -ServiceAccount "DOMAIN\svc_secureboot"
.EXAMPLE .\Deploy-OrchestratorTask.ps1 -AggregationInputPath "\\server\SecureBootData$" -ReportBasePath "C:\SecureBootReports"
.EXAMPLE # Implementeer met behulp van de WinCS-methode in plaats van AvailableUpdatesPolicy .\Deploy-OrchestratorTask.ps1 -AggregationInputPath "\\server\SecureBootData$" -ReportBasePath "C:\SecureBootReports" -UseWinCS
.EXAMPLE .\Deploy-OrchestratorTask.ps1 -Uninstall #>
[CmdletBinding()] param( [Parameter(Verplicht = $false)] [tekenreeks]$AggregationInputPath, [Parameter(Verplicht = $false)] [tekenreeks]$ReportBasePath, [Parameter(Verplicht = $false)] [tekenreeks]$TargetOU, [Parameter(Verplicht = $false)] [int]$PollIntervalMinutes = 30, [Parameter(Verplicht = $false)] [switch]$UseWinCS, [Parameter(Verplicht = $false)] [tekenreeks]$WinCSKey = "F33E0C8E002", [Parameter(Verplicht = $false)] [tekenreeks]$ServiceAccount = "SYSTEM", [Parameter(Verplicht = $false)] [tekenreeks]$AllowListPath, [Parameter(Verplicht = $false)] [tekenreeks]$AllowADGroup, [Parameter(Verplicht = $false)] [tekenreeks]$ExclusionListPath, [Parameter(Verplicht = $false)] [tekenreeks]$ExcludeADGroup, [Parameter(Verplicht = $false)] [tekenreeks]$ScriptPath, [Parameter(Verplicht = $false)] [switch]$Uninstall )
$ErrorActionPreference = "Stop" $TaskName = "SecureBoot-Rollout-Orchestrator" $DownloadUrl = "https://aka.ms/getsecureboot" $DownloadSubPage = "Implementatie- en bewakingsvoorbeelden"
# ================================================================== #DEPENDENCY VALIDATION# ==================================================================
function Test-ScriptDependencies { <# . SYNOPSIS Hiermee wordt gecontroleerd of alle vereiste scripts aanwezig zijn.. BESCHRIJVING Controleert op vereiste scriptafhankelijkheden en biedt downloadinstructies als deze ontbreken.#> param( [Parameter(Verplicht = $true)] [tekenreeks]$ScriptDirectory, [Parameter(Verplicht = $true)] [tekenreeks[]]$RequiredScripts ) $missingScripts = @() foreach ($script in $RequiredScripts) { $scriptPath = Join-Path $ScriptDirectory $script if (-not (testpad $scriptPath)) { $missingScripts += $script } } if ($missingScripts.Count -gt 0) { Write-Host "" Write-Host ("=" * 70) -VoorgrondKleur Rood Write-Host "ONTBREKENDE AFHANKELIJKHEDEN" -ForegroundColor Red Write-Host ("=" * 70) -VoorgrondKleur Rood Write-Host "" Write-Host 'De volgende vereiste scripts zijn niet gevonden:' -ForegroundColor Yellow foreach ($script in $missingScripts) { Write-Host " - $script" -ForegroundColor White } Write-Host "" Write-Host 'Download de meest recente scripts van:' -ForegroundColor Cyan Write-Host " URL: $DownloadUrl" -ForegroundColor White Write-Host "Navigeer naar: '$DownloadSubPage'" -ForegroundColor White Write-Host "" Write-Host 'Alle scripts uitpakken naar dezelfde map en opnieuw uitvoeren'. -ForegroundColor Yellow Write-Host "" $false retourneren } $true retourneren }
# Required scripts for orchestrator deployment $requiredScripts = @( "Start-SecureBootRolloutOrchestrator.ps1", "Aggregate-SecureBootData.ps1", "Deploy-GPO-SecureBootCollection.ps1", "Detect-SecureBootCertUpdateStatus.ps1", "Get-SecureBootRolloutStatus.ps1", "Enable-SecureBootUpdateTask.ps1" )
if (-not (Test-ScriptDependencies -ScriptDirectory $PSScriptRoot -RequiredScripts $requiredScripts)) { afsluiten 1 }
# ================================================================== # UNINSTALL# ==================================================================
if ($Uninstall) { Write-Host "" Write-Host 'Geplande taak verwijderen: $TaskName' -ForegroundColor Yellow $existingTask = Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue if ($existingTask) { Stop-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false Write-Host 'Taak is verwijderd'. -ForegroundColor Green } else { Write-Host 'Taak niet gevonden'. -VoorgrondKleur Grijs } afsluiten 0 }
# ================================================================== # VALIDATIE# ==================================================================
if (-not $AggregationInputPath -or -not $ReportBasePath) { Write-Host 'ERROR: -AggregationInputPath en -ReportBasePath zijn vereist'. -ForegroundColor Red Write-Host "" Write-Host "Example:" -ForegroundColor Yellow Write-Host ' .\Deploy-OrchestratorTask.ps1 -AggregationInputPath "\\server\SecureBootData$" -ReportBasePath "C:\SecureBootReports"' afsluiten 1 }
# Find orchestrator script if (-not $ScriptPath) { $ScriptPath = Join-Path $PSScriptRoot 'Start-SecureBootRolloutOrchestrator.ps1' }
if (-not (Test-Path $ScriptPath)) { Write-Host "ERROR: Orchestrator script not found: $ScriptPath" -ForegroundColor Red afsluiten 1 }
# Find aggregation script (needed by orchestrator) $aggregateScript = Join-Path $PSScriptRoot 'Aggregate-SecureBootData.ps1' if (-not (testpad $aggregateScript)) { Write-Host 'WAARSCHUWING: Aggregate-SecureBootData.ps1 niet gevonden in scriptmap' -ForegroundColor Yellow Write-Host 'Orchestrator kan mislukken als dit script niet kan worden gevonden.' -ForegroundColor Yellow }
Write-Host "" Write-Host ("=" * 70) -ForegroundColor Cyan Write-Host "Secure Boot Rollout Orchestrator - Task Deployment" -ForegroundColor Cyan Write-Host ("=" * 70) -ForegroundColor Cyan Write-Host ""
# For display, show relative paths (script names only) $displayScriptPath = Split-Path $ScriptPath -Leaf
Write-Host "Configuration:" -ForegroundColor Yellow Write-Host "Taaknaam: $TaskName" Write-Host Orchestrator: $displayScriptPath Write-Host 'Invoerpad: $AggregationInputPath' Write-Host 'Rapportpad: $ReportBasePath' Write-Host " Doel-OE: $(if ($TargetOU) { $TargetOU } else { '(domain root)' })" Write-Host pollinterval: $PollIntervalMinutes minuten Write-Host 'Serviceaccount: $ServiceAccount' Write-Host "Implementatiemethode: $(if ($UseWinCS) { "WinCS (WinCsFlags.exe)" } else { "AvailableUpdatesPolicy (GPO)" })" if ($UseWinCS) { Write-Host "WinCS-sleutel: $WinCSKey" } Write-Host ""
# ================================================================== # GPO DETECTION - AUTO-DEPLOY IF MISSING# ==================================================================
$CollectionGPOName = "SecureBoot-EventCollection" $deployGpoScript = Join-Path $PSScriptRoot 'Deploy-GPO-SecureBootCollection.ps1'
# Check if GroupPolicy module is available if (Get-Module -ListAvailable -Name GroupPolicy) { Import-Module GroupPolicy -ErrorAction SilentlyContinue Write-Host "Controleren op detectie GPO..." -VoorgrondKleur Geel probeer { # Haal het domein op uit het AggregationInputPath (bijvoorbeeld \\domain\share) $domainFromPath = if ($AggregationInputPath -match ^\\\\([^\\\]+)\\') { $matches[1] } else { $env:USERDNSDOMAIN } # Controleer of groepsbeleidsobject bestaat $existingGpo = Get-GPO -Name $CollectionGPOName -ErrorAction SilentlyContinue if ($existingGpo) { Write-Host 'Detectie-GPO gevonden: $CollectionGPOName' -ForegroundColor Green } else { Write-Host "" Write-Host ("=" * 70) -VoorgrondKleur Geel Write-Host "DETECTIE-GPO NIET GEVONDEN" -VoorgrondKleur Geel Write-Host ("=" * 70) -VoorgrondKleur Geel Write-Host "" Write-Host 'Het detectie-GPO '$CollectionGPOName' is niet gevonden.' -ForegroundColor Yellow Write-Host 'Dit groepsbeleidsobject is vereist voor het verzamelen van apparaatstatusgegevens.' -ForegroundColor Yellow Write-Host "" # Vraag de gebruiker of ze het groepsbeleidsobject nu willen implementeren Write-Host 'Wilt u het detectie-GPO nu implementeren? (Y/N)" -ForegroundColor Cyaan $response = Read-Host if ($response -match ^[Yy]') { Write-Host "" Write-Host "Implementatie van GPO starten..." -ForegroundColor Cyan Write-Host "" # Parameters bouwen voor GPO-implementatie $gpoParams = @{ DomainName = $domainFromPath CollectionSharePath = $AggregationInputPath ScriptSourcePath = Join-Path $PSScriptRoot 'Detect-SecureBootCertUpdateStatus.ps1' } if ($TargetOU) { $gpoParams.OUPath = $TargetOU } else { # Gebruik AutoDetectOU om de gebruiker te laten selecteren $gpoParams.AutoDetectOU = $true } # Voer het GPO-implementatiescript uit & $deployGpoScript @gpoParams if ($LASTEXITCODE -ne 0) { Write-Host 'Er zijn mogelijk problemen opgetreden bij de implementatie van het groepsbeleidsobject. Controleer de uitvoer hierboven." -ForegroundColor Yellow Write-Host 'U kunt doorgaan met de orchestrator-implementatie of druk op Ctrl+C om af te breken.' -ForegroundColor Yellow Write-Host "" Read-Host "Druk op Enter om door te gaan" } else { Write-Host "" Write-Host 'Detectie-GPO geïmplementeerd!' -ForegroundColor Green Write-Host "" } } else { Write-Host "" Write-Host 'Implementatie van GPO overslaan. De orchestrator ontvangt geen apparaatgegevens" -ForegroundColor Yellow Write-Host 'totdat het detectie-GPO handmatig is geïmplementeerd'. -ForegroundColor Yellow Write-Host "" Write-Host 'Als u het detectie-GPO later wilt implementeren, voert u het volgende uit: - ForegroundColor Cyan Write-Host " .\Deploy-GPO-SecureBootCollection.ps1 -DomainName ""$domainFromPath"" -AutoDetectOU" -ForegroundColor White Write-Host "" } } } catch { Write-Host " Kan niet controleren op GPO: $($_. Exception.Message)" -ForegroundColor Yellow Write-Host " Doorgaan met orchestrator-implementatie..." -ForegroundColor Gray } } else { Write-Host 'GroupPolicy-module niet beschikbaar - GPO-controle overslaan' -ForegroundColor Gray Write-Host Ervoor zorgen dat detectie-GPO afzonderlijk wordt geïmplementeerd. -ForegroundColor Gray }
Write-Host ""
# ================================================================== #BUILD ARGUMENTS# ==================================================================
$arguments = @( "-NoProfile" "-ExecutionPolicy Bypass" "-Bestand ""$ScriptPath""" "-AggregationInputPath ""$AggregationInputPath"" "-ReportBasePath ""$ReportBasePath"" "-PollIntervalMinutes $PollIntervalMinutes" )
if ($TargetOU) { $arguments += "-TargetOU ""$TargetOU"" }
if ($UseWinCS) { $arguments += "-UseWinCS" $arguments += "-WinCSKey ""$WinCSKey""" }
if ($AllowListPath) { $arguments += "-AllowListPath ""$AllowListPath"" }
if ($AllowADGroup) { $arguments += "-AllowADGroup ""$AllowADGroup""" }
if ($ExclusionListPath) { $arguments += "-ExclusionListPath ""$ExclusionListPath"" }
if ($ExcludeADGroup) { $arguments += "-ExcludeADGroup ""$ExcludeADGroup""" }
$argumentString = $arguments -join " "
# Don't display raw arguments with full paths - it's confusing for published scripts # De taak gebruikt het volledige pad intern
# ================================================================== # GEPLANDE TAAK maken# ==================================================================
# Check for existing task $existingTask = Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue if ($existingTask) { Write-Host 'Taak bestaat al. Bijwerken... -VoorgrondKleur Geel Stop-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false }
# Create task action $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument $argumentString -WorkingDirectory $PSScriptRoot
# Create trigger - run once, immediately (orchestrator loops internally) $trigger = New-ScheduledTaskTrigger -Once -At (Get-Date). AddMinutes(1)
# Create principal if ($ServiceAccount -eq "SYSTEM") { $principal = New-ScheduledTaskPrincipal -UserId "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest } else { # Lokale accountindeling normaliseren: COMPUTERNAAM\Gebruiker -> Gebruiker # Register-ScheduledTask accepteert geen COMPUTERNAME\User of .\User voor lokale accounts $taskUser = $ServiceAccount if ($ServiceAccount -match ^$([regex]::Escape($env:COMPUTERNAME))\\(.+)$") { $taskUser = $Matches[1] Write-Host "Opmerking: Lokaal account gedetecteerd, met behulp van '$taskUser' voor taakregistratie" -ForegroundColor Gray }
# Prompt for password Write-Host 'Wachtwoord invoeren voor $ServiceAccount' -ForegroundColor Yellow $cred = Get-Credential -UserName $taskUser -Bericht 'Serviceaccountreferenties voor geplande taak' if (-not $cred) { Write-Host 'Referentievermelding geannuleerd. Afgebroken." -ForegroundColor Red afsluiten 1 } $principal = New-ScheduledTaskPrincipal -UserId $taskUser -LogonType Password -RunLevel Highest }
# Task settings $settings = New-ScheduledTaskSettingsSet ' -AllowStartIfOnBatteries ' -DontStopIfGoingOnBatteries ' -StartWhenAvailable ' -RunOnlyIfNetworkAvailable ' -RestartCount 3 ' -RestartInterval (New-TimeSpan -minutes 5) ' -ExecutionTimeLimit (New-TimeSpan -Days 30) # Allow long-running
# Register task probeer { if ($ServiceAccount -eq "SYSTEM") { Register-ScheduledTask -TaskName $TaskName -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Description 'Secure Boot Certificate Rollout - Automated GPO deployment' } else { # Gebruik New-ScheduledTask om de principal (met RunLevel Highest) in te sluiten in een taakobject, # registreer u vervolgens met -InputObject + -User/-Password (afzonderlijke parameters ingesteld van -Principal) $taskDefinition = New-ScheduledTask -Action $action -Trigger $trigger -Principal $principal -Settings $settings $taskDefinition.Description = "Secure Boot Certificate Rollout - Automated GPO deployment" # Opmerking: Register-ScheduledTask vereist een wachtwoord voor tekst zonder opmaak - er is geen overbelasting van SecureString $netCred = $cred. GetNetworkCredential() Register-ScheduledTask -TaskName $TaskName -InputObject $taskDefinition -User $taskUser -Password $netCred.Password -ErrorAction Stop $netCred = $null } Write-Host 'Geplande taak is gemaakt!' -VoorgrondKleur Groen } catch { Write-Host 'Kan de geplande taak niet maken: $($_. Exception.Message)" -ForegroundColor Red afsluiten 1 }
# ================================================================== SNELKOPPELING # CREATE-STATUS# ==================================================================
$statusScript = Join-Path $PSScriptRoot "Get-SecureBootRolloutStatus.ps1" if (testpad $statusScript) { Write-Host "" Write-Host 'Voer uit om de implementatiestatus te controleren: - ForegroundColor Yellow Write-Host " .\Get-SecureBootRolloutStatus.ps1 -ReportBasePath ""$ReportBasePath"" -ForegroundColor Cyan }
# ================================================================== # OUTPUT# ==================================================================
Write-Host "" Write-Host ("=" * 70) -VoorgrondKleur Groen Write-Host "DEPLOYMENT COMPLETE" -ForegroundColor Green Write-Host ("=" * 70) -VoorgrondKleur Groen Write-Host "" Write-Host 'De orchestrator begint over ongeveer 1 minuut'. -ForegroundColor White Write-Host "" Write-Host "MONITORING:" -ForegroundColor Yellow Write-Host " Taakstatus weergeven: Get-ScheduledTask -Taaknaam '$TaskName' | Selecteer Status' Write-Host " Taaklogboek weergeven: Get-Content '$ReportBasePath\RolloutState\Orchestrator_$(Get-Date -Format 'yyyyMMdd').log' -Tail 50" Write-Host " Implementatiestatus weergeven: Get-Content '$ReportBasePath\RolloutState\RolloutState.json' | ConvertFrom-Json" Write-Host "Dashboard weergeven: start '$ReportBasePath\Aggregation_*\SecureBoot_Dashboard*.html'" Write-Host "Snelle status: .\Get-SecureBootRolloutStatus.ps1 -ReportBasePath '$ReportBasePath'" Write-Host "" Write-Host "MANAGEMENT:" -ForegroundColor Yellow Write-Host "Handmatig starten: Start-ScheduledTask -TaskName '$TaskName'" Write-Host "Stop: Stop-ScheduledTask -TaskName '$TaskName'" Write-Host verwijderen: .\Deploy-OrchestratorTask.ps1 -Uninstall Write-Host ""