WICHTIG Dieser Artikel, der dieses Beispielskript enthält, wurde eingestellt. Ab den Windows-Updates, die am und nach dem 12. Mai 2026 veröffentlicht wurden, befindet sich das Beispielskript auf Ihrem Gerät im Ordner %systemroot%\SecureBoot\ExampleRolloutScripts .
Kopieren Sie dieses Beispielskript, fügen Sie es ein, und ändern Sie es nach Bedarf für Ihre Umgebung:
<# . SYNOPSIS Stellt den Secure Boot Rollout Orchestrator als geplanten Windows-Task bereit.
.DESCRIPTION Erstellt eine geplante Aufgabe, die den Orchestrator kontinuierlich im Hintergrund ausführt.Der Task wird mit einer Umgehungsausführungsrichtlinie ausgeführt, sodass keine Sicherheitsaufforderungen angezeigt werden. Der Orchestrator führt Folgendes aus: – Abfragen von Geräteupdates im angegebenen Intervall - Automatisches Generieren von Wellen und Bereitstellen von GPOs – Fahren Sie fort, bis alle berechtigten Geräte aktualisiert wurden. Überwachen des Fortschritts mit: Get-SecureBootRolloutStatus.ps1
.PARAMETER AggregationInputPath UNC-Pfad zu JSON-Gerätedaten (aus erkennungs-GPO)
.PARAMETER ReportBasePath Lokaler Pfad für Berichte und Zustandsdateien
.PARAMETER TargetOU Organisationseinheit zum Verknüpfen von Gruppenrichtlinienobjekten (optional – Standardmäßig domänenstamm)
.PARAMETER PollIntervalMinutes Minuten zwischen status Überprüfungen. Standardwert: 30
.PARAMETER UseWinCS Verwenden Sie WinCS (Windows Configuration System) anstelle des AvailableUpdatesPolicy-GPO.Wenn diese Option aktiviert ist, wird WinCsFlags.exe geplante Aufgabe für Endpunkte anstelle des Registrierungs-GPO bereitgestellt.
.PARAMETER WinCSKey Der WinCS-Schlüssel für die Konfiguration des sicheren Starts. Standard: F33E0C8E002
.PARAMETER ServiceAccount Konto zum Ausführen der Aufgabe. Standard: SYSTEM Verwenden Sie für Domänenvorgänge ein Domänenadministratordienstkonto.
.PARAMETER AllowListPath Pfad zu einer Datei mit Hostnamen, die für den Rollout (Ziel-/Pilotrollout) zulässig sind.Unterstützt .txt (ein Hostname pro Zeile) oder .csv (mit der Spalte Hostname/Computername/Name).Wenn angegeben, werden NUR diese Geräte in den Rollout einbezogen.
.PARAMETER AllowADGroup Name einer AD-Sicherheitsgruppe, die Computerkonten enthält, die zugelassen werden sollen.Beispiel: "SecureBoot-Pilot-Computers"
.PARAMETER ExclusionListPath Pfad zu einer Datei mit Hostnamen, die vom Rollout ausgeschlossen werden sollen (VIP/Executive-Geräte).Unterstützt .txt (ein Hostname pro Zeile) oder .csv (mit der Spalte Hostname/Computername/Name).
.PARAMETER ExcludeADGroup Name einer AD-Sicherheitsgruppe, die auszuschließende Computerkonten enthält.Beispiel: "VIP-Computer"
.PARAMETER ScriptPath Pfad zum Orchestratorskript. Standard: Derselbe Ordner wie dieses Skript.
.PARAMETER Uninstall Entfernen des geplanten Vorgangs
.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 # Bereitstellen mithilfe der WinCS-Methode anstelle von AvailableUpdatesPolicy .\Deploy-OrchestratorTask.ps1 -AggregationInputPath "\\server\SecureBootData$" -ReportBasePath "C:\SecureBootReports" -UseWinCS
.EXAMPLE .\Deploy-OrchestratorTask.ps1 -Uninstall #>
[CmdletBinding()] param( [Parameter(Mandatory = $false)] [Zeichenfolge]$AggregationInputPath, [Parameter(Mandatory = $false)] [Zeichenfolge]$ReportBasePath, [Parameter(Mandatory = $false)] [Zeichenfolge]$TargetOU, [Parameter(Mandatory = $false)] [int]$PollIntervalMinutes = 30, [Parameter(Mandatory = $false)] [Switch]$UseWinCS, [Parameter(Mandatory = $false)] [string]$WinCSKey = "F33E0C8E002", [Parameter(Mandatory = $false)] [string]$ServiceAccount = "SYSTEM", [Parameter(Mandatory = $false)] [Zeichenfolge]$AllowListPath, [Parameter(Mandatory = $false)] [Zeichenfolge]$AllowADGroup, [Parameter(Mandatory = $false)] [Zeichenfolge]$ExclusionListPath, [Parameter(Mandatory = $false)] [Zeichenfolge]$ExcludeADGroup, [Parameter(Mandatory = $false)] [Zeichenfolge]$ScriptPath, [Parameter(Mandatory = $false)] [switch]$Uninstall )
$ErrorActionPreference = "Stop" $TaskName = "SecureBoot-Rollout-Orchestrator" $DownloadUrl = "https://aka.ms/getsecureboot" $DownloadSubPage = "Beispiele für Bereitstellung und Überwachung"
# ================================================================== ## ==================================================================ZUR ÜBERPRÜFUNG VON ABHÄNGIGKEITEN
function Test-ScriptDependencies { <# . SYNOPSIS Überprüft, ob alle erforderlichen Skripts vorhanden sind.. BESCHREIBUNG Überprüft, ob erforderliche Skriptabhängigkeiten vorhanden sind, und stellt Downloadanweisungen bereit, falls diese fehlen.#> param( [Parameter(Mandatory = $true)] [Zeichenfolge]$ScriptDirectory, [Parameter(Mandatory = $true)] [string[]]$RequiredScripts ) $missingScripts = @() foreach ($script in $RequiredScripts) { $scriptPath = Join-Path $ScriptDirectory $script if (-not (Test-Path $scriptPath)) { $missingScripts += $script } } if ($missingScripts.Count -gt 0) { Write-Host "" Write-Host ("=" * 70) -ForegroundColor Red Write-Host "MISSING DEPENDENCIES" -ForegroundColor Red Write-Host ("=" * 70) -ForegroundColor Red Write-Host "" Write-Host "Die folgenden erforderlichen Skripts wurden nicht gefunden:" -ForegroundColor Yellow foreach ($script in $missingScripts) { Write-Host " - $script" -ForegroundColor White } Write-Host "" Write-Host "Bitte laden Sie die neuesten Skripts von herunter: " -ForegroundColor Cyan Write-Host " URL: $DownloadUrl" -ForegroundColor White Write-Host "Navigieren Sie zu: '$DownloadSubPage'" -ForegroundColor White Write-Host "" Write-Host "Extrahieren Sie alle Skripts in dasselbe Verzeichnis, und führen Sie sie erneut aus." -ForegroundColor Yellow Write-Host "" $false zurückgeben } $true zurückgeben }
# 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)) { Ausgang 1 }
# ================================================================== # UNINSTALL# ==================================================================
if ($Uninstall) { Write-Host "" Write-Host "Geplante Aufgabe entfernen: $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 "Task erfolgreich entfernt". -ForegroundColor Green } else { Write-Host "Aufgabe nicht gefunden" -ForegroundColor Gray } Exit 0 }
# ================================================================== # VALIDATION# ==================================================================
if (-not $AggregationInputPath -or -not $ReportBasePath) { Write-Host "ERROR: -AggregationInputPath und -ReportBasePath sind erforderlich." -ForegroundColor Red Write-Host "" Write-Host "Example:" -ForegroundColor Yellow Write-Host ' .\Deploy-OrchestratorTask.ps1 -AggregationInputPath "\\server\SecureBootData$" -ReportBasePath "C:\SecureBootReports"' Ausgang 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 Ausgang 1 }
# Find aggregation script (needed by orchestrator) $aggregateScript = Join-Path $PSScriptRoot "Aggregate-SecureBootData.ps1" if (-not (Test-Path $aggregateScript)) { Write-Host "WARNUNG: Aggregate-SecureBootData.ps1 im Skriptverzeichnis nicht gefunden" -ForegroundColor Yellow Write-Host " Orchestrator schlägt möglicherweise fehl, wenn dieses Skript nicht gefunden wird." -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 " Aufgabenname: $TaskName" Write-Host " Orchestrator: $displayScriptPath" Write-Host "Eingabepfad: $AggregationInputPath" Write-Host "Berichtspfad: $ReportBasePath" Write-Host " Ziel-ORGANISATIONSeinheit: $(if ($TargetOU) { $TargetOU } else { '(domain root)' })" Write-Host " Abrufintervall: $PollIntervalMinutes Minuten" Write-Host "Dienstkonto: $ServiceAccount" Write-Host " Bereitstellungsmethode: $(if ($UseWinCS) { "WinCS (WinCsFlags.exe)" } else { "AvailableUpdatesPolicy (GPO)" })" if ($UseWinCS) { Write-Host "WinCS-Taste: $WinCSKey" } Write-Host ""
# ================================================================== # GPO-ERKENNUNG – AUTOMATISCHE BEREITSTELLUNG, WENN# ==================================================================FEHLT
$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 "Überprüfung auf Erkennungs-GPO..." -ForegroundColor Yellow try { # Abrufen der Domäne aus aggregationInputPath (z. B. \\domain\share) $domainFromPath = if ($AggregationInputPath -match '^\\\\([^\\]+)\\') { $matches[1] } else { $env:USERDNSDOMAIN } # Überprüfen, ob das Gruppenrichtlinienobjekt vorhanden ist $existingGpo = Get-GPO -Name $CollectionGPOName -ErrorAction SilentlyContinue if ($existingGpo) { Write-Host "Erkennungs-GPO gefunden: $CollectionGPOName" -ForegroundColor Green } else { Write-Host "" Write-Host ("=" * 70) -ForegroundColor Yellow Write-Host "ERKENNUNGS-GPO NICHT GEFUNDEN" -ForegroundColor Yellow Write-Host ("=" * 70) -ForegroundColor Yellow Write-Host "" Write-Host "Das Erkennungs-GPO '$CollectionGPOName' wurde nicht gefunden." -ForegroundColor Yellow Write-Host "Dieses Gruppenrichtlinienobjekt ist erforderlich, um Geräte- status Daten zu sammeln." -ForegroundColor Yellow Write-Host "" # Fragen Sie Benutzer, ob sie das Gruppenrichtlinienobjekt jetzt bereitstellen möchten. Write-Host "Möchten Sie das Erkennungs-GPO jetzt bereitstellen? (Y/N)" -ForegroundColor Cyan $response = Read-Host if ($response -match '^[Yy]') { Write-Host "" Write-Host "GPO-Bereitstellung wird gestartet..." -ForegroundColor Cyan Write-Host "" # Buildparameter für die GPO-Bereitstellung $gpoParams = @{ DomainName = $domainFromPath CollectionSharePath = $AggregationInputPath ScriptSourcePath = Join-Path $PSScriptRoot "Detect-SecureBootCertUpdateStatus.ps1" } if ($TargetOU) { $gpoParams.OUPath = $TargetOU } else { # Verwenden Sie AutoDetectOU, um dem Benutzer die Auswahl zu ermöglichen. $gpoParams.AutoDetectOU = $true } # Ausführen des GPO-Bereitstellungsskripts & $deployGpoScript @gpoParams if ($LASTEXITCODE -ne 0) { Write-Host "Bei der GPO-Bereitstellung sind möglicherweise Probleme aufgetreten. Überprüfen Sie die obige Ausgabe." -ForegroundColor Yellow Write-Host "Sie können mit der Orchestratorbereitstellung fortfahren, oder drücken Sie STRG+C, um den Abbruch abzubrechen." -ForegroundColor Yellow Write-Host "" Read-Host "Drücken Sie die EINGABETASTE, um fortzufahren" } else { Write-Host "" Write-Host "Erkennungs-GPO erfolgreich bereitgestellt!" -ForegroundColor Green Write-Host "" } } else { Write-Host "" Write-Host "Überspringen der GPO-Bereitstellung. Der Orchestrator empfängt keine Gerätedaten" -ForegroundColor Yellow Write-Host " bis das Erkennungs-GPO manuell bereitgestellt wird." -ForegroundColor Yellow Write-Host "" Write-Host "Um das Erkennungs-GPO später bereitzustellen, führen Sie aus:" -ForegroundColor Cyan Write-Host ".\Deploy-GPO-SecureBootCollection.ps1 -DomainName '"$domainFromPath'" -AutoDetectOU" -ForegroundColor White Write-Host "" } } } catch { Write-Host " GPO kann nicht überprüft werden: $($_. Exception.Message)" -ForegroundColor Yellow Write-Host "Fortsetzen der Orchestratorbereitstellung..." -ForegroundColor Gray } } else { Write-Host " GroupPolicy-Modul nicht verfügbar – GPO-Überprüfung übersprungen" -ForegroundColor Gray Write-Host "Sicherstellen, dass das Erkennungs-GPO separat bereitgestellt wird." -ForegroundColor Gray }
Write-Host ""
# ================================================================== # BUILD ARGUMENTS# ==================================================================
$arguments = @( "-NoProfile" "-ExecutionPolicy Bypass" "-File '"$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 # Die Aufgabe verwendet intern den vollständigen Pfad.
# ================================================================== # CREATE SCHEDULED TASK# ==================================================================
# Check for existing task $existingTask = Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue if ($existingTask) { Write-Host "Task ist bereits vorhanden. Wird aktualisiert..." -ForegroundColor Yellow 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 { # Normalize local account format: COMPUTERNAME\User -> User # Register-ScheduledTask akzeptiert COMPUTERNAME\User oder .\User für lokale Konten nicht. $taskUser = $ServiceAccount if ($ServiceAccount -match "^$([regex]::Escape($env:COMPUTERNAME))\\(.+)$") { $taskUser = $Matches[1] Write-Host "Hinweis: Lokales Konto mit "$taskUser" für die Aufgabenregistrierung erkannt" -ForegroundColor Gray }
# Prompt for password Write-Host "Kennwort für $ServiceAccount eingeben" -ForegroundColor Yellow $cred = Get-Credential -UserName $taskUser -Message "Anmeldeinformationen des Dienstkontos für geplante Aufgabe" if (-not $cred) { Write-Host "Anmeldeinformationseintrag wurde abgebrochen. Abbruch." -ForegroundColor Red Ausgang 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 try { 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 { # Verwenden Sie New-ScheduledTask, um den Prinzipal (mit RunLevel Highest) in ein Aufgabenobjekt einzubetten. # dann mit -InputObject + -User/-Password registrieren (separater Parametersatz von -Principal) $taskDefinition = New-ScheduledTask -Action $action -Trigger $trigger -Principal $principal -Settings $settings $taskDefinition.Description = "Rollout des Zertifikats für den sicheren Start – Automatisierte GPO-Bereitstellung" # Hinweis: Register-ScheduledTask erfordert ein Nur-Text-Kennwort – es ist keine SecureString-Überladung vorhanden. $netCred = $cred. GetNetworkCredential() Register-ScheduledTask -TaskName $TaskName -InputObject $taskDefinition -User $taskUser -Password $netCred.Password -ErrorAction Stop $netCred = $null } Write-Host "Geplante Aufgabe erfolgreich erstellt!" -ForegroundColor Green } catch { Write-Host "Fehler beim Erstellen einer geplanten Aufgabe: $($_. Exception.Message)" -ForegroundColor Red Ausgang 1 }
# ================================================================== # CREATE STATUS SHORTCUT# ==================================================================
$statusScript = Join-Path $PSScriptRoot "Get-SecureBootRolloutStatus.ps1" if (Testpfad $statusScript) { Write-Host "" Write-Host "Zum Überprüfen des Rollouts status ausführen:" -ForegroundColor Yellow Write-Host " .\Get-SecureBootRolloutStatus.ps1 -ReportBasePath '"$ReportBasePath'"" -ForegroundColor Cyan }
# ================================================================== # OUTPUT# ==================================================================
Write-Host "" Write-Host ("=" * 70) -ForegroundColor Green Write-Host "DEPLOYMENT COMPLETE" -ForegroundColor Green Write-Host ("=" * 70) -ForegroundColor Green Write-Host "" Write-Host "Der Orchestrator wird in ca. 1 Minute gestartet." -ForegroundColor White Write-Host "" Write-Host "MONITORING:" -ForegroundColor Yellow Write-Host " Task status anzeigen: Get-ScheduledTask -TaskName '$TaskName' | Wählen Sie "State" aus. Write-Host " Taskprotokoll anzeigen: Get-Content '$ReportBasePath\RolloutState\Orchestrator_$(Get-Date -Format 'yyyyMMdd').log' -Tail 50" Write-Host " Rolloutstatus anzeigen: Get-Content "$ReportBasePath\RolloutState\RolloutState.json" | ConvertFrom-Json" Write-Host " Dashboard anzeigen: Start '$ReportBasePath\Aggregation_*\SecureBoot_Dashboard*.html'" Write-Host " Quick status: .\Get-SecureBootRolloutStatus.ps1 -ReportBasePath '$ReportBasePath'" Write-Host "" Write-Host "MANAGEMENT:" -ForegroundColor Yellow Write-Host "Manuell starten: Start-ScheduledTask -TaskName '$TaskName'" Write-Host "Stop: Stop-ScheduledTask -TaskName '$TaskName'" Write-Host "Remove: .\Deploy-OrchestratorTask.ps1 -Uninstall" Write-Host ""