이 샘플 스크립트를 복사하여 붙여넣고 환경에 필요한 대로 수정합니다.
<# . 시놉시스 보안 부팅 롤아웃 오케스트레이터를 Windows 예약 작업으로 배포합니다.
.DESCRIPTION 백그라운드에서 지속적으로 오케스트레이터를 실행하는 예약된 작업을 만듭니다.작업은 무시 실행 정책을 사용하여 실행되므로 보안 프롬프트가 표시되지 않습니다. 오케스트레이터는 다음을 수행합니다. - 지정된 간격에 대한 디바이스 업데이트 폴링 - 자동으로 웨이브 생성 및 GPO 배포 - 적격 디바이스가 모두 업데이트될 때까지 계속합니다 . 다음을 사용하여 진행률 모니터링: Get-SecureBootRolloutStatus.ps1
.PARAMETER AggregationInputPath JSON 디바이스 데이터에 대한 UNC 경로(검색 GPO에서)
.PARAMETER ReportBasePath 보고서 및 상태 파일의 로컬 경로
.PARAMETER TargetOU GPO를 연결하는 OU(선택 사항 - 기본값: 도메인 루트)
.PARAMETER PollIntervalMinutes 상태 확인 사이의 분입니다. 기본값: 30
.PARAMETER UseWinCS AvailableUpdatesPolicy GPO 대신 WinCS(Windows 구성 시스템)를 사용합니다.사용하도록 설정하면 WinCsFlags.exe 예약된 작업을 레지스트리 GPO 대신 엔드포인트에 배포합니다.
.PARAMETER WinCSKey 보안 부팅 구성에 대한 WinCS 키입니다. 기본값: F33E0C8E002
.PARAMETER ServiceAccount 작업을 실행할 계정입니다. 기본값: SYSTEM 도메인 작업의 경우 도메인 관리 서비스 계정을 사용합니다.
.PARAMETER ScriptPath 오케스트레이터 스크립트의 경로입니다. 기본값: 이 스크립트와 동일한 폴더입니다.
.PARAMETER Uninstall 예약된 작업 제거
.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 # AvailableUpdatesPolicy 대신 WinCS 메서드를 사용하여 배포 .\Deploy-OrchestratorTask.ps1 -AggregationInputPath "\\server\SecureBootData$" -ReportBasePath "C:\SecureBootReports" -UseWinCS
.EXAMPLE .\Deploy-OrchestratorTask.ps1 -제거 #>
[CmdletBinding()] param( [Parameter(Mandatory = $false)] [string]$AggregationInputPath, [Parameter(Mandatory = $false)] [string]$ReportBasePath, [Parameter(Mandatory = $false)] [string]$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)] [string]$ScriptPath [Parameter(Mandatory = $false)] [switch]$Uninstall )
$ErrorActionPreference = "Stop" $TaskName = "SecureBoot-Rollout-Orchestrator" $DownloadUrl = "https://aka.ms/getsecureboot" $DownloadSubPage = "배포 및 모니터링 샘플"
# ============================================================================ # 종속성 유효성 검사 # ============================================================================
function Test-ScriptDependencies { <# . 시놉시스 필요한 모든 스크립트가 있는지 확인합니다.. 설명 필요한 스크립트 종속성을 확인하고 누락된 경우 다운로드 지침을 제공합니다.#> param( [Parameter(Mandatory = $true)] [string]$ScriptDirectory, [Parameter(Mandatory = $true)] [string[]]$RequiredScripts ) $missingScripts = @() foreach($RequiredScripts $script) { $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 "누락된 종속성" -ForegroundColor Red Write-Host ("=" * 70) -ForegroundColor Red Write-Host "" Write-Host "다음 필수 스크립트를 찾을 수 없습니다." -ForegroundColor 노란색 foreach($missingScripts $script) { Write-Host " - $script" -ForegroundColor White } Write-Host "" Write-Host "에서 최신 스크립트를 다운로드하세요:" -ForegroundColor Cyan Write-Host " URL: $DownloadUrl" -ForegroundColor White Write-Host "탐색: '$DownloadSubPage'" -ForegroundColor White Write-Host "" Write-Host "모든 스크립트를 동일한 디렉터리에 추출하고 다시 실행합니다." -ForegroundColor Yellow Write-Host "" return $false } return $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)) { 종료 1 }
# ============================================================================ # 제거 # ============================================================================
if ($Uninstall) { Write-Host "" Write-Host "예약된 작업 제거: $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 "작업이 성공적으로 제거되었습니다." -ForegroundColor 녹색 } else { Write-Host "작업을 찾을 수 없습니다." -ForegroundColor 회색 } 종료 0 }
# ============================================================================ # 유효성 검사 # ============================================================================
if (-not $AggregationInputPath -or -not $ReportBasePath) { Write-Host "ERROR: -AggregationInputPath 및 -ReportBasePath가 필요합니다." -ForegroundColor Red Write-Host "" Write-Host "Example:" -ForegroundColor Yellow Write-Host ' .\Deploy-OrchestratorTask.ps1 -AggregationInputPath "\\server\SecureBootData$" -ReportBasePath "C:\SecureBootReports"' 종료 1 }
# Find orchestrator script if (-not $ScriptPath) { $ScriptPath = Join-Path $PSScriptRoot "Start-SecureBootRolloutOrchestrator.ps1" }
if (-not (Test-Path $ScriptPath)) { Write-Host "ERROR: Orchestrator 스크립트를 찾을 수 없음: $ScriptPath" -ForegroundColor Red 종료 1 }
# Find aggregation script (needed by orchestrator) $aggregateScript = Join-Path $PSScriptRoot "Aggregate-SecureBootData.ps1" if (-not (Test-Path $aggregateScript)) { Write-Host "경고: 스크립트 디렉터리에서 Aggregate-SecureBootData.ps1 찾을 수 없음" -ForegroundColor 노란색 Write-Host "이 스크립트를 찾을 수 없으면 오케스트레이터가 실패할 수 있습니다." -ForegroundColor Yellow }
Write-Host "" Write-Host ("=" * 70) -ForegroundColor Cyan Write-Host "보안 부팅 롤아웃 오케스트레이터 - 작업 배포" -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 " 작업 이름: $TaskName" Write-Host " Orchestrator: $displayScriptPath" Write-Host " 입력 경로: $AggregationInputPath" Write-Host " 보고서 경로: $ReportBasePath" Write-Host " 대상 OU: $(if ($TargetOU) { $TargetOU } else { '(domain root)' })" Write-Host "폴링 간격: $PollIntervalMinutes 분" Write-Host " 서비스 계정: $ServiceAccount" Write-Host " 배포 방법: $(if ($UseWinCS) { "WinCS (WinCsFlags.exe)" } else { "AvailableUpdatesPolicy (GPO)" })" if ($UseWinCS) { Write-Host " WinCS 키: $WinCSKey" } Write-Host ""
# ============================================================================ # GPO 검색 - 누락된 경우 자동 배포 # ============================================================================
$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 "검색 GPO 확인..." -ForegroundColor 노란색 try { # AggregationInputPath에서 도메인 가져오기(예: \\domain\share) $domainFromPath = if ($AggregationInputPath -match '^\\\\([^\\]+)\\') { $matches[1] } else { $env:USERDNSDOMAIN } # GPO가 있는지 확인 $existingGpo = Get-GPO -Name $CollectionGPOName -ErrorAction SilentlyContinue if ($existingGpo) { Write-Host " 검색 GPO 발견: $CollectionGPOName" -ForegroundColor 녹색 } else { Write-Host "" Write-Host ("=" * 70) -ForegroundColor Yellow Write-Host "검색 GPO를 찾을 수 없음" -ForegroundColor 노란색 Write-Host ("=" * 70) -ForegroundColor Yellow Write-Host "" Write-Host "검색 GPO '$CollectionGPOName'을(를) 찾을 수 없습니다." -ForegroundColor Yellow Write-Host "이 GPO는 디바이스 상태 데이터를 수집하는 데 필요합니다." -ForegroundColor Yellow Write-Host "" # 사용자에게 지금 GPO를 배포할 것인지 물어봅니다. Write-Host "지금 검색 GPO를 배포하시겠습니까? (Y/N)" -ForegroundColor Cyan $response = 읽기 호스트 if ($response -match '^[Yy]') { Write-Host "" Write-Host "GPO 배포 시작..." -ForegroundColor Cyan Write-Host "" # GPO 배포를 위한 빌드 매개 변수 $gpoParams = @{ DomainName = $domainFromPath CollectionSharePath = $AggregationInputPath ScriptSourcePath = Join-Path $PSScriptRoot "Detect-SecureBootCertUpdateStatus.ps1" } if ($TargetOU) { $gpoParams.OUPath = $TargetOU } else { # AutoDetectOU를 사용하여 사용자가 선택할 수 있도록 허용 $gpoParams.AutoDetectOU = $true } # GPO 배포 스크립트 실행 & $deployGpoScript @gpoParams if ($LASTEXITCODE -ne 0) { Write-Host "GPO 배포에 문제가 있을 수 있습니다. 위의 출력을 검토합니다." -ForegroundColor Yellow Write-Host "오케스트레이터 배포를 계속하거나 Ctrl+C를 눌러 중단할 수 있습니다." -ForegroundColor Yellow Write-Host "" Read-Host "계속하려면 Enter 키를 누릅니다." } else { Write-Host "" Write-Host "GPO 검색이 성공적으로 배포되었습니다!" -ForegroundColor Green Write-Host "" } } else { Write-Host "" Write-Host "GPO 배포 건너뛰기. 오케스트레이터가 디바이스 데이터를 수신하지 않습니다." -ForegroundColor Yellow "검색 GPO가 수동으로 배포될 때까지" Write-Host. -ForegroundColor Yellow Write-Host "" Write-Host "나중에 검색 GPO를 배포하려면 run:" -ForegroundColor Cyan Write-Host " .\Deploy-GPO-SecureBootCollection.ps1 -DomainName '"$domainFromPath'" -AutoDetectOU" -ForegroundColor White Write-Host "" } } } catch { Write-Host " GPO에 대해 검사 수 없습니다. $($_) Exception.Message)" -ForegroundColor Yellow Write-Host "오케스트레이터 배포 계속..." -ForegroundColor Gray } } else { Write-Host " GroupPolicy 모듈을 사용할 수 없음 - GPO 검사 건너뛰기" -ForegroundColor Gray Write-Host "검색 GPO가 별도로 배포되었는지 확인합니다." -ForegroundColor Gray }
Write-Host ""
# ============================================================================ # BUILD 인수 # ============================================================================
$arguments = @( "-NoProfile" "-ExecutionPolicy 바이패스" "-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 # 태스크는 내부적으로 전체 경로를 사용합니다.
# ============================================================================ # 예약된 작업 만들기 # ============================================================================
# Check for existing task $existingTask = Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue if ($existingTask) { Write-Host "작업이 이미 있습니다. 업데이트 중..." -ForegroundColor 노란색 Stop-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false }
# Create task action $action = New-ScheduledTaskAction -"powershell.exe" 실행 -argument $argumentString -WorkingDirectory $PSScriptRoot
# Create trigger - run once, immediately (orchestrator loops internally) $trigger = New-ScheduledTaskTrigger -한 번 -At(Get-Date). AddMinutes(1)
# Create principal if ($ServiceAccount -eq "SYSTEM") { $principal = New-ScheduledTaskPrincipal -UserId "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest } else { # 도메인 계정에 대한 암호 프롬프트 Write-Host "$ServiceAccount 암호 입력" -ForegroundColor Yellow $cred = Get-Credential -UserName $ServiceAccount -메시지 "예약된 작업에 대한 서비스 계정 자격 증명" $principal = New-ScheduledTaskPrincipal -UserId $ServiceAccount -LogonType 암호 -RunLevel Highest }
# Task settings $settings = New-ScheduledTaskSettingsSet ' -AllowStartIfOnBatteries ' -DontStopIfGoingOnBatteries ' -StartWhenAvailable ' -RunOnlyIfNetworkAvailable ' -RestartCount 3 ' -RestartInterval(New-TimeSpan -Minutes 5) ' -ExecutionTimeLimit(New-TimeSpan -Days 30) # 장기 실행 허용
# Register task try { if ($ServiceAccount -eq "SYSTEM") { Register-ScheduledTask -TaskName $TaskName -Action $action -Trigger $trigger -Principal $principal -Settings $settings -description "보안 부팅 인증서 롤아웃 - 자동화된 GPO 배포" } else { Register-ScheduledTask -TaskName $TaskName -Action $action -Trigger $trigger -Principal $principal -Settings $settings -description "Secure Boot Certificate Rollout - Automated GPO deployment" -User $ServiceAccount -Password $cred. GetNetworkCredential(). 암호 } Write-Host "예약된 작업이 성공적으로 생성되었습니다!" -ForegroundColor Green } catch { Write-Host "예약된 작업을 만들지 못했습니다. $($_) Exception.Message)" -ForegroundColor Red 종료 1 }
# ============================================================================ # 만들기 상태 바로 가기 # ============================================================================
$statusScript = Join-Path $PSScriptRoot "Get-SecureBootRolloutStatus.ps1" if (Test-Path $statusScript) { Write-Host "" Write-Host "롤아웃 상태 검사 실행:" -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 "오케스트레이터는 약 1분 후에 시작됩니다." -ForegroundColor White Write-Host "" Write-Host "MONITORING:" -ForegroundColor Yellow Write-Host " 작업 상태 보기: Get-ScheduledTask -TaskName '$TaskName' | 상태 선택" Write-Host " 작업 로그 보기: Get-Content '$ReportBasePath\RolloutState\Orchestrator_$(Get-Date -Format 'yyyyMMdd').log' -Tail 50" Write-Host " 출시 상태 보기: '$ReportBasePath\RolloutState\RolloutState.json' Get-Content | ConvertFrom-Json" Write-Host "dashboard 보기: '$ReportBasePath\Aggregation_*\SecureBoot_Dashboard*.html' 시작" Write-Host "빠른 상태: .\Get-SecureBootRolloutStatus.ps1 -ReportBasePath '$ReportBasePath'" Write-Host "" Write-Host "MANAGEMENT:" -ForegroundColor Yellow Write-Host "수동으로 시작: Start-ScheduledTask -TaskName '$TaskName'" Write-Host "중지: Stop-ScheduledTask -TaskName '$TaskName'" Write-Host "제거: .\Deploy-OrchestratorTask.ps1 -제거" Write-Host ""