Copie y pegue este script de ejemplo y modifíquelo según sea necesario para su entorno:
<# . SINOOPSIS Implementa el organizador de la implementación de arranque seguro como tarea programada de Windows.
.DESCRIPTION Crea una tarea programada que ejecuta el organizador continuamente en segundo plano.La tarea se ejecuta con la directiva de ejecución de omisión, por lo que no aparecen mensajes de seguridad. El organizador hará lo siguiente: - Sondeo de actualizaciones de dispositivos en el intervalo especificado - Generar ondas automáticamente e implementar GPO - Continúa hasta que todos los dispositivos aptos se actualicen Supervisar el progreso con: Get-SecureBootRolloutStatus.ps1
.PARAMETER AggregationInputPath Ruta de acceso UNC a los datos del dispositivo JSON (desde GPO de detección)
.PARAMETER ReportBasePath Ruta de acceso local para informes y archivos de estado
.PARAMETER TargetOU Unidad organizativa para vincular GPO (opcional: valores predeterminados en la raíz del dominio)
.PARAMETER PollIntervalMinutes Minutos entre comprobaciones de estado. Valor predeterminado: 30
.PARAMETER UseWinCS Use WinCS (Sistema de configuración de Windows) en lugar de AvailableUpdatesPolicy GPO.Cuando está habilitada, implementa WinCsFlags.exe tarea programada en puntos de conexión en lugar de GPO del Registro.
.PARAMETER WinCSKey La clave de WinCS para la configuración de arranque seguro. Valor predeterminado: F33E0C8E002
.PARAMETER ServiceAccount Cuenta para ejecutar la tarea. Valor predeterminado: SISTEMA Para operaciones de dominio, use una cuenta de servicio de administración de dominio.
.PARAMETER ScriptPath Ruta de acceso al script del organizador. Valor predeterminado: misma carpeta que este script.
.PARAMETER Uninstall Quitar la tarea programada
.EXAMPLE .\Deploy-OrchestratorTask.ps1 -AggregationInputPath "\\servidor\SecureBootData$" -ReportBasePath "C:\SecureBootReports" -ServiceAccount "DOMAIN\svc_secureboot"
.EXAMPLE .\Deploy-OrchestratorTask.ps1 -AggregationInputPath "\\servidor\SecureBootData$" -ReportBasePath "C:\SecureBootReports"
.EXAMPLE # Implementar mediante el método WinCS en lugar de AvailableUpdatesPolicy .\Deploy-OrchestratorTask.ps1 -AggregationInputPath "\\servidor\SecureBootData$" -ReportBasePath "C:\SecureBootReports" -UseWinCS
.EXAMPLE .\Deploy-OrchestratorTask.ps1 -Desinstalar #>
[CmdletBinding()] parámetro( [Parámetro(Obligatorio = $false)] [cadena]$AggregationInputPath, [Parámetro(Obligatorio = $false)] [cadena]$ReportBasePath, [Parámetro(Obligatorio = $false)] [cadena]$TargetOU, [Parámetro(Obligatorio = $false)] [int]$PollIntervalMinutes = 30, [Parámetro(Obligatorio = $false)] [conmutador]$UseWinCS, [Parámetro(Obligatorio = $false)] [string]$WinCSKey = "F33E0C8E002", [Parámetro(Obligatorio = $false)] [string]$ServiceAccount = "SYSTEM", [Parameter(Mandatory = $false)] [cadena]$ScriptPath, [Parámetro(Obligatorio = $false)] [conmutador]$Uninstall )
$ErrorActionPreference = "Stop" $TaskName = "SecureBoot-Rollout-Orchestrator" $DownloadUrl = "https://aka.ms/getsecureboot" $DownloadSubPage = "Ejemplos de implementación y supervisión"
# ============================================================================ VALIDACIÓN DE DEPENDENCIA # # ============================================================================
function Test-ScriptDependencies { <# . SINOOPSIS Valida que todos los scripts necesarios están presentes.. DESCRIPCIÓN Comprueba las dependencias de script necesarias y proporciona instrucciones de descarga si faltan.#> parámetro( [Parámetro(Obligatorio = $true)] [cadena]$ScriptDirectory, [Parámetro(Obligatorio = $true)] [cadena[]]$RequiredScripts ) $missingScripts = @() foreach ($script en $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 " DEPENDENCIAS QUE FALTAN" -ForegroundColor Red Write-Host ("=" * 70) -ForegroundColor Red Write-Host "" Write-Host "No se han encontrado los siguientes scripts necesarios:" -ForegroundColor Yellow foreach ($script en $missingScripts) { Write-Host " - $script" -ForegroundColor White } Write-Host "" Write-Host "Descarga los scripts más recientes de:" -ForegroundColor Cyan Write-Host " URL: $DownloadUrl" -ForegroundColor White Write-Host " Vaya a: '$DownloadSubPage'" -ForegroundColor White Write-Host "" Write-Host "Extraer todos los scripts al mismo directorio y volver a ejecutarlos". -ForegroundColor Yellow Write-Host "" devolver $false } devolver $true }
# 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)) { salir 1 }
# ============================================================================ # DESINSTALAR # ============================================================================
if ($Uninstall) { Write-Host "" Write-Host "Quitar tarea programada: $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 "Tarea se ha quitado correctamente". -ForegroundColor Verde } else { Write-Host "No se encontró la tarea". -ForegroundColor Gray } salir 0 }
# ============================================================================ # VALIDACIÓN # ============================================================================
if (-not $AggregationInputPath -or -not $ReportBasePath) { Write-Host "ERROR: -AggregationInputPath y -ReportBasePath son necesarios". -ForegroundColor Red Write-Host "" Write-Host "Ejemplo:" -ForegroundColor Yellow Write-Host ' .\Deploy-OrchestratorTask.ps1 -AggregationInputPath "\\servidor\SecureBootData$" -ReportBasePath "C:\SecureBootReports"' salir 1 }
# Find orchestrator script if (-not $ScriptPath) { $ScriptPath = Join-Path $PSScriptRoot "Start-SecureBootRolloutOrchestrator.ps1" }
if (-not (Test-Path $ScriptPath)) { Write-Host "ERROR: No se encuentra el script del organizador: $ScriptPath" -ForegroundColor Red salir 1 }
# Find aggregation script (needed by orchestrator) $aggregateScript = Join-Path $PSScriptRoot "Aggregate-SecureBootData.ps1" if (-not (Test-Path $aggregateScript)) { Write-Host "ADVERTENCIA: Aggregate-SecureBootData.ps1 no se encuentra en el directorio script" -ForegroundColor Yellow Write-Host "El organizador puede producir un error si no encuentra este script". -ForegroundColor Yellow }
Write-Host "" Write-Host ("=" * 70) -ForegroundColor Cyan Write-Host "Organizador de implementación de arranque seguro: implementación de tareas" -ForegroundColor Cyan Write-Host ("=" * 70) -ForegroundColor Cyan Write-Host ""
# For display, show relative paths (script names only) $displayScriptPath = Split-Path $ScriptPath -Hoja
Write-Host "Configuration:" -ForegroundColor Yellow Write-Host " Nombre de la tarea: $TaskName" Write-Host " Organizador: $displayScriptPath" Write-Host " Ruta de entrada: $AggregationInputPath" Write-Host " Ruta del informe: $ReportBasePath" Write-Host " OU de destino: $(if ($TargetOU) { $TargetOU } else { '(domain root)' })" Write-Host " Intervalo de sondeo: minutos de $PollIntervalMinutes" Write-Host " Cuenta de servicio: $ServiceAccount" Write-Host " Método de implementación: $(if ($UseWinCS) { "WinCS (WinCsFlags.exe)" } else { "AvailableUpdatesPolicy (GPO)" })" if ($UseWinCS) { Write-Host " Tecla WinCS: $WinCSKey" } Write-Host ""
# ============================================================================ # DETECCIÓN DE GPO: IMPLEMENTACIÓN AUTOMÁTICA SI FALTA # ============================================================================
$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 "Comprobación de GPO de detección..." -ForegroundColor Yellow prueba { # Obtener el dominio de AggregationInputPath (por ejemplo, \\dominio\recurso compartido) $domainFromPath = if ($AggregationInputPath -match '^\\\\([^\\]+)\\') { $matches[1] } else { $env:USERDNSDOMAIN } # Comprobar si existe GPO $existingGpo = Get-GPO -Name $CollectionGPOName -ErrorAction SilentlyContinue if ($existingGpo) { Write-Host "GPO de detección encontrado: $CollectionGPOName" -ForegroundColor Green } else { Write-Host "" Write-Host ("=" * 70) -ForegroundColor Yellow Write-Host " GPO DE DETECCIÓN NO encontrado" -ForegroundColor Yellow Write-Host ("=" * 70) -ForegroundColor Yellow Write-Host "" Write-Host "No se encontró el '$CollectionGPOName' de GPO de detección". -ForegroundColor Yellow Write-Host "Este GPO es necesario para recopilar datos de estado del dispositivo". -ForegroundColor Yellow Write-Host "" # Preguntar al usuario si desea implementar el GPO ahora Write-Host "¿Desea implementar el GPO de detección ahora? (Y/N)" -ForegroundColor Cyan $response = Read-Host if ($response -match '^[Yy]') { Write-Host "" Write-Host "Lanzamiento de la implementación de GPO..." -ForegroundColor Cyan Write-Host "" # Parámetros de compilación para la implementación de GPO $gpoParams = @{ DomainName = $domainFromPath CollectionSharePath = $AggregationInputPath ScriptSourcePath = Join-Path $PSScriptRoot "Detect-SecureBootCertUpdateStatus.ps1" } if ($TargetOU) { $gpoParams.OUPath = $TargetOU } else { # Use AutoDetectOU para permitir que el usuario seleccione $gpoParams.AutoDetectOU = $true } # Ejecutar el script de implementación de GPO & $deployGpoScript @gpoParams if ($LASTEXITCODE -ne 0) { Write-Host "La implementación de GPO puede haber encontrado problemas. Revisa el resultado anterior". -ForegroundColor Yellow Write-Host "Puedes continuar con la implementación del organizador o presionar Ctrl+C para anular". -ForegroundColor Yellow Write-Host "" Read-Host "Presione Entrar para continuar" } else { Write-Host "" Write-Host "¡Gpo de detección implementado correctamente!" -ForegroundColor Green Write-Host "" } } else { Write-Host "" Write-Host "Omitir la implementación de GPO. El organizador no recibirá datos del dispositivo" -ForegroundColor Yellow Write-Host "hasta que el GPO de detección se implemente manualmente". -ForegroundColor Yellow Write-Host "" Write-Host "Para implementar el GPO de detección más adelante, ejecute:" -ForegroundColor Cyan Write-Host " .\Deploy-GPO-SecureBootCollection.ps1 -DomainName '"$domainFromPath'" -AutoDetectOU" -ForegroundColor White Write-Host "" } } } captura { Write-Host " No se puede comprobar el GPO: $($_. Exception.Message)" -ForegroundColor Yellow Write-Host " Continuar con la implementación del organizador..." -ForegroundColor Gray } } else { Write-Host " Módulo GroupPolicy no disponible: omitir la comprobación de GPO" -ForegroundColor Gray Write-Host "Asegúrese de que el GPO de detección se implementa por separado". -ForegroundColor Gray }
Write-Host ""
# ============================================================================ # ARGUMENTOS DE COMPILACIÓN # ============================================================================
$arguments = @( "-NoProfile" "-ExecutionPolicy Bypass" "-File '"$ScriptPath'"" "-AggregationInputPath '"$AggregationInputPath'"" "-ReportBasePath '"$ReportBasePath'"" "-PollIntervalMinutes $PollIntervalMinutes" )
if ($TargetOU) { $arguments += "-TargetOU '"$TargetOU'"" }
if ($UseWinCS) { $arguments += "-UseWinCS" $arguments += "-WinCSKey '"$WinCSKey'"" }
$argumentString = $arguments -join " "
# Don't display raw arguments with full paths - it's confusing for published scripts # La tarea usará la ruta de acceso completa internamente
# ============================================================================ # CREAR TAREA PROGRAMADA # ============================================================================
# Check for existing task $existingTask = Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue if ($existingTask) { Write-Host "La tarea ya existe. Actualizando..." -ForegroundColor Amarillo 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 { # Solicitud de contraseña para una cuenta de dominio Write-Host "Escriba la contraseña de $ServiceAccount" -ForegroundColor Yellow $cred = Get-Credential -UserName $ServiceAccount -Message "Credenciales de la cuenta de servicio para la tarea programada" $principal = New-ScheduledTaskPrincipal -UserId $ServiceAccount -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) # Permitir la ejecución larga
# Register task prueba { if ($ServiceAccount -eq "SYSTEM") { Register-ScheduledTask -TaskName $TaskName -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Description "Implementación de certificados de arranque seguro - implementación automatizada de GPO" } else { Register-ScheduledTask -TaskName $TaskName -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Description "Implementación de certificados de arranque seguro - implementación automatizada de GPO" -User $ServiceAccount -Password $cred. GetNetworkCredential(). Contraseña } Write-Host "Tarea programada creada correctamente!" -ForegroundColor green } captura { Write-Host "No se pudo crear la tarea programada: $($_. Exception.Message)" -ForegroundColor Red salir 1 }
# ============================================================================ # CREAR ACCESO DIRECTO A ESTADO # ============================================================================
$statusScript = Join-Path $PSScriptRoot "Get-SecureBootRolloutStatus.ps1" if ($statusScript ruta de prueba) { Write-Host "" Write-Host "Para comprobar el estado de implementación, ejecute:" -ForegroundColor Yellow Write-Host " .\Get-SecureBootRolloutStatus.ps1 -ReportBasePath '"$ReportBasePath'"" -ForegroundColor Cyan }
# ============================================================================ # SALIDA # ============================================================================
Write-Host "" Write-Host ("=" * 70) -ForegroundColor verde Write-Host "DEPLOYMENT COMPLETE" -ForegroundColor verde Write-Host ("=" * 70) -ForegroundColor verde Write-Host "" Write-Host "El organizador se iniciará en aproximadamente 1 minuto". -ForegroundColor White Write-Host "" Write-Host "SUPERVISIÓN:" -ForegroundColor Yellow Write-Host " Ver estado de tarea: Get-ScheduledTask -TaskName '$TaskName' | Seleccionar estado" Write-Host " Ver registro de tareas: Get-Content '$ReportBasePath\RolloutState\Orchestrator_$(Get-Date -Format 'yyyyMMdd').log' -Tail 50" Write-Host " Ver estado de implementación: Get-Content '$ReportBasePath\RolloutState\RolloutState.json' | ConvertFrom-Json" Write-Host " Ver panel: Iniciar '$ReportBasePath\Aggregation_*\SecureBoot_Dashboard*.html'" Write-Host " Estado rápido: .\Get-SecureBootRolloutStatus.ps1 -ReportBasePath '$ReportBasePath'" Write-Host "" Write-Host "ADMINISTRACIÓN:" -ForegroundColor Amarillo Write-Host " Iniciar manualmente: Start-ScheduledTask -TaskName '$TaskName'" Write-Host " Detener: Stop-ScheduledTask -TaskName '$TaskName'" Write-Host " Eliminar: .\Deploy-OrchestratorTask.ps1 -Uninstall" Write-Host ""