Nukopijuokite ir įklijuokite šį scenarijaus pavyzdį ir modifikuokite, kiek reikia jūsų aplinkai:
<# . ANOTACIJA GPO diegimo scenarijus, skirtas saugiosios įkrovos įvykių rinkiniui Sukuria ir susieja GPO, kad rinkinio scenarijus būtų diegiamas kaip suplanuota užduotis
.DESCRIPTION Šis scenarijus automatizuoja saugiosios įkrovos įvykių rinkinio diegimą per Grupės strategija.Ji sukuria GPO su: - Suplanuota užduotis, kuri kasdien vykdo rinkinio scenarijų - Tinkamos teisės rašyti į centrinę dalį - WMI filtrai, skirti konkrečioms OS versijoms
.PARAMETER GPOName Naujo GPO pavadinimas
.PARAMETER DomainName Paskirties domeno FQDN
.PARAMETER OUPath Ou (-ų), su kurio (-ių) susieti GPO, išskirtinis vardas.Priima kelis OU kaip masyvą. Nebūtina, jei nurodyta -AutoDetectOU.
.PARAMETER AutoDetectOU Pereikite į interaktyvią sąrašą ir pasirinkite OU iš "Active Directory".Kai nurodyta, -OUPath yra pasirinktinis.
.PARAMETER CollectionSharePath UNC kelias, kur bus saugomi rinkimo rezultatai
.PARAMETER ScriptSourcePath Kelias, kuriuo saugomas rinkinio scenarijus (bus nukopijuotas į SYSVOL)
.PARAMETER RandomDelayHours Valandų skaičius, norint atsitiktinai paskirstyti scenarijaus vykdymą galiniais punktais.Tai neleidžia visiems kompiuteriams rašyti į bendrinimą vienu metu.Numatytoji reikšmė: 4 valandos. Leistinas diapazonas: 1–24 valandos. Rekomenduojamos reikšmės: - 1–10 000 įrenginių: 4 valandos (numatytoji reikšmė) - 10 K-50 K įrenginiai: 8 val. - 50 K ir daugiau įrenginių: 12–24 val.
.EXAMPLE .\Deploy-GPO-SecureBootCollection.ps1 -DomainName "contoso.com" -OUPath "OU=Workstations,DC=contoso,DC=com"
.EXAMPLE .\Deploy-GPO-SecureBootCollection.ps1 -DomainName "contoso.com" -OUPath "OU=Workstations,DC=contoso,DC=com" -RandomDelayHours 8
.EXAMPLE .\Deploy-GPO-SecureBootCollection.ps1 -DomainName "contoso.com" - AutoDetectOU Išvardijami visi domeno OU ir raginama pasirinkti.
.EXAMPLE .\Deploy-GPO-SecureBootCollection.ps1 -DomainName "contoso.com" -OUPath @("OU=Workstations,DC=contoso,DC=com", "OU=Laptops,DC=contoso,DC=com") Susieja GPO su keliais vienu paleidimu.
.NOTES Būtina: "Active Directory PowerShell" modulis, Grupės strategija modulis Turi būti vykdomos su domeno Administratorius arba įgaliotojo GPO kūrimo teisėmis #>
[CmdletBinding()] param( [Parametras(Privalomas = $false)] [eilutė]$GPOName = "SecureBoot-EventCollection", [Parametras(Privalomas = $false)] [eilutė]$DomainName, [Parametras(Privalomas = $false)] [eilutė[]$OUPath, [Parametras(Privalomas = $false)] [jungiklis]$AutoDetectOU, [Parametras(Privalomas = $false)] [eilutė]$CollectionSharePath = "\\$DomainName\NETLOGON\SecureBootLogs", [Parametras(Privalomas = $false)] [eilutė]$ScriptSourcePath = ".\Detect-SecureBootCertUpdateStatus.ps1", [Parametras(Privalomas = $false)] [ValidateSet("Daily", "Weekly", "AtStartup")] [eilutė]$Schedule = "Daily", [Parametras(Privalomas = $false)] [eilutė]$ScheduleTime = "14:00", [Parametras(Privalomas = $false)] [ValidateRange(1, 24)] [sveikasis skaičius]$RandomDelayHours = 4 )
#Requires -Modules ActiveDirectory, GroupPolicy #Requires – 5.1 versija
$ErrorActionPreference = "Stop" $DownloadUrl = "https://aka.ms/getsecureboot" $DownloadSubPage = "Diegimo ir stebėjimo pavyzdžiai"
# ============================================================================ # PRIKLAUSOMYBĖS TIKRINIMAS # ============================================================================
function Test-ScriptDependencies { param( [Parametras(Privalomas = $true)] [eilutė]$ScriptDirectory, [Parametras(Privalomas = $true)] [eilutė[]$RequiredScripts ) $missingScripts = @() foreach ($script in $RequiredScripts) { $scriptPath = Join-Path $ScriptDirectory $script jei (-not (testo kelias $scriptPath)) { $missingScripts += $script } } jei ($missingScripts.Count -gt 0) { Write-Host "" Write-Host (=" * 70) - priekinio planopalva raudona Write-Host " MISSING DEPENDENCIES" -ForegroundColor Red Write-Host (=" * 70) - priekinio planopalva raudona Write-Host " Write-Host "Nerasta šių būtinų scenarijų:" -Priekinio planopalva Geltona foreach ($script in $missingScripts) { Write-Host " - $script" - Priekinio planopalva balta } Write-Host Write-Host "Atsisiųskite naujausius scenarijus iš:" -ForegroundColor Cyan Write-Host " URL: $DownloadUrl" - Priekinio planopalva balta Write-Host " Pereiti į: "$DownloadSubPage" - priekinio planopalva balta Write-Host Write-Host "Išskleisti visus scenarijus į tą patį katalogą ir paleisti iš naujo." -Priekinio planopalva Geltona Write-Host grąžinimo $false } grąžinimo $true }
# The Detect script is required - it gets deployed to endpoints via GPO $requiredScripts = @( "Detect-SecureBootCertUpdateStatus.ps1" )
if (-not (Test-ScriptDependencies -ScriptDirectory $PSScriptRoot -RequiredScripts $requiredScripts)) { išeiti iš 1 }
# ============================================================================ # AUTOMATINIS DOMENO VARDO APTIKIMAS # ============================================================================
if (-not $DomainName) { $DomainName = $env:USERDNSDOMAIN jei (-not $DomainName) { # Pabandykite gauti iš AD modulio išbandykite { Import-Module ActiveDirectory - ErrorAction Stop $DomainName = (Get-ADDomain). DNSRoot } sugauti { Write-Host "KLAIDA: nepavyko automatiškai aptikti domeno vardo." -Priekinio planopalva raudona Write-Host "Nurodykite -DomainName parametrą." -Priekinio planopalva Geltona Write-Host Write-Host "Example:" -ForegroundColor Gray Write-Host ".\Deploy-GPO-SecureBootCollection.ps1 -DomainName contoso.com -AutoDetectOU" -Priekinio planopalva balta išeiti iš 1 } } Write-Host "Auto-detected domain: $DomainName" -ForegroundColor Green }
# Set CollectionSharePath default if not explicitly provided jei (ne $PSBoundParameters.ContainsKey('CollectionSharePath')) { $CollectionSharePath = "\\$DomainName\NETLOGON\SecureBootLogs" }
Write-Host "============================================" -ForegroundColor Cyan Write-Host "Secure Boot Collection - GPO Deployment" -ForegroundColor Cyan Write-Host "============================================" – priekinio planopalva žydra
# Validate prerequisites Write-Host "'n[1/6] Tikrinamos būtinosios sąlygos..." -Priekinio planopalva geltona
if (-not (Get-Module -ListAvailable -Name ActiveDirectory)) { throw "ActiveDirectory modulis nerastas. Įdiekite RSAT įrankius." }
if (-not (Get-Module -ListAvailable -Name GroupPolicy)) { throw "GroupPolicy modulis nerastas. Įdiekite RSAT įrankius." }
Import-Module ActiveDirectory Import-Module GroupPolicy"
# Validate domain connectivity išbandykite { $domain = Get-ADDomain -Server $DomainName Write-Host " Prisijungta prie domeno: $($domain. DNSRoot)" -Priekinio planopalva Žalia } sugauti { throw "Negalima prisijungti prie domeno: $DomainName. Klaida: $_" }
# Handle OU selection jei ($AutoDetectOU) { Write-Host "N Aptinkama OU domene..." -Priekinio planocolor žydra $allOUs = Get-ADOrganizationalUnit -Filter * -Server $DomainName | Sort-Object DistinguishedName | Select-Object @{n='Indeksas'; E={0}}, vardas, išskirtinis vardas # Indeksų priskyrimas skirta ($i = 0; $i -lt $allOUs.Count; $i++) { $allOUs[$i]. Indeksas = $i + 1 } Write-Host "nėra pasiekiamų OU:" - priekinio planopalva geltona Write-Host " --------------------------------------------------------------------- " - Priekinio planocolor DarkGray $allOUs | ForEach-Object { Write-Host (" {0,3}) {1}" -f $_. Indeksas, $_. DistinguishedName) - priekinio planopalva balta } Write-Host " --------------------------------------------------------------------- " - Priekinio planocolor DarkGray Write-Host " Patarimas: įveskite kableliais atskirtus skaičius, kad pasirinktumėte kelis skustukus (pvz., 1,3,5)" -Priekinio planopalva DarkGray Write-Host " Įveskite "A", kad pasirinktumėte VISUS "OUs" -Priekinio planopalva DarkGray Write-Host $selection = Read-Host " Pasirinkite OU(-ai), kad susietumėte GPO" jei ($selection -eq 'A' -arba $selection -eq 'a') { $OUPath = $allOUs.DistinguishedName Write-Host " Selected ALL $($OUPath.Count) OUs" -ForegroundColor Green } dar { $indices = $selection -split ',' | ForEach-Object { [sveikasis skaičius]$_. Trim() } $OUPath = @() foreach ($idx in $indices) { $selected = $allOUs | Where-Object { $_. Indeksas -eq $idx } jei ($selected) { $OUPath += $selected. Išskirtinis vardas } dar { Write-Warning "Neleistina rodyklė: $idx – praleidžiama" } } } jei ($OUPath.Count -eq 0) { throw "Nepasirinkta jokių OU. Nutraukiamas." } Write-Host "'n Selected $($OUPath.Count) OU(s):" -ForegroundColor Green $OUPath | ForEach-Object { Write-Host " - $_" -Priekinio planopalva Pilka } } elseif (-not $OUPath -or $OUPath.Count -eq 0) { throw "Turi būti nurodyta Arba -OUPath, arba -AutoDetectOU." } dar { # Tikrinti kiekvieną OU yra foreach ($path in $OUPath) { išbandykite { $ou = Get-ADOrganizationalUnit -Identity $path -Server $DomainName Write-Host " Target OU rastas: $($ou. Name) -ForegroundColor Green } sugauti { throw "OU nerastas: $path" } } }
# Validate source script exists jei (-not (testo kelias $ScriptSourcePath)) { throw "Rinkinio scenarijus nerastas: $ScriptSourcePath" }
# Step 2: Create collection share structure Write-Host "'n[2/6] Rinkinio bendrinimo nustatymas..." -Priekinio planopalva Geltona
$sysvolScriptPath = "\\$DomainName\SYSVOL\$DomainName\Scripts\SecureBootCollection"
# Create SYSVOL script folder jei (-not (testo kelias $sysvolScriptPath)) { New-Item -ItemType katalogas -Kelias $sysvolScriptPath -Priverstinai | Nu neapibrėžta reikšmė (Out-Null) Write-Host " Sukurtas SYSVOL scenarijaus aplankas: $sysvolScriptPath" -ForegroundColor Žalia }
# Copy collection script to SYSVOL $destScript = Join-Path $sysvolScriptPath "Detect-SecureBootCertUpdateStatus.ps1"
# Remove existing destination if it's a directory (fix for Copy-Item bug) jei (Test-Path $destScript -PathType konteineris) { Remove-Item $destScript -Recurse -Force }
Copy-Item -Path $ScriptSourcePath -Destination $destScript -Force Write-Host " Copied collection script to SYSVOL" -ForegroundColor Green
# Create a wrapper script that calls the main script with parameters $wrapperScript = @" #Secure Boot Event Collection Wrapper # Automatiškai generavo Deploy-GPO-SecureBootCollection.ps1
`$ErrorActionPreference = 'SilentlyContinue'
# Configuration "$CollectionShare = "$CollectionSharePath" '$ScriptPath = '$sysvolScriptPath\Detect-SecureBootCertUpdateStatus.ps1'
# Run collection with -OutputPath parameter if (bandymo kelias "$ScriptPath) { & $ScriptPath -OutputPath $CollectionShare } dar { Write-EventLog -LogName Application -Source "SecureBootCollection" - EventId 1001 -EntryType klaida - Pranešimas "Rinkinio scenarijus nerastas: "$ScriptPath" } " @
$wrapperPath = Join-Path $sysvolScriptPath "Run-SecureBootCollection.ps1" $wrapperScript | Out-File -FilePath $wrapperPath -Encoding UTF8 -Force Write-Host " Sukurtas aplanko scenarijus" - Priekinio planopalva Žalia
# Create collection share (if on a file server) Write-Host " Rinkinio bendrinimo kelias: $CollectionSharePath" -ForegroundColor Cyan Write-Host " PASTABA: įsitikinkite, kad ši bendrinimo vieta yra su "Domeno kompiuteriai" rašymo prieiga" - "ForegroundColor Yellow"
# Step 3: Create the GPO Write-Host "'n[3/6] Kuriamas Grupės strategija objektas..." -Priekinio planopalva geltona
# Check if GPO already exists $existingGPO = Get-GPO -Name $GPOName -Domain $DomainName -ErrorAction SilentlyContinue
if ($existingGPO) { Write-Host GPO $GPOName jau yra. Naujinama..." – geltona priekinio plano spalva $gpo = $existingGPO } dar { $gpo = New-GPO -Name $GPOName -Domain $DomainName -Comment "Deploys Secure Boot event collection script to endpoints" Write-Host " Sukurta GPO: $GPOName" - Priekinio planocolor žalia }
# Step 4: Configure Scheduled Task via GPO Preferences Write-Host "'n[4/6] Konfigūruojama suplanuota užduotis..." -Priekinio planopalva Geltona
# Build the scheduled task XML # RandomDelay išskleidžia vykdymą tarp galinių punktų, kad būtų išvengta serverio perkrovos Write-Host " Atsitiktinė delsa: $RandomDelayHours valandos (apkrovos pasklidimas laivyne)" -ForegroundColor Cyan
$taskTrigger = switch ($Schedule) { "Kasdien" { @" <CalendarTrigger> <StartBoundary>2024-01-01T${ScheduleTime}:00</StartBoundary> <Įgalintas>teisingas</ įgalintas> <ScheduleByDay> <Dienosintervalis>1</DaysInterval> </ScheduleByDay> <RandomDelay>PT${RandomDelayHours}H</RandomDelay> </CalendarTrigger> "@ } "Kas savaitę" { @" <CalendarTrigger> <StartBoundary>2024-01-01T${ScheduleTime}:00</StartBoundary> <Įgalintas>teisingas</ įgalintas> <ScheduleByWeek> <WeekInterval>1</WeeksInterval> <DaysOfWeek> <trečiadienis / > <>DaysOfWeek </ScheduleByWeek> <RandomDelay>PT${RandomDelayHours}H</RandomDelay> </CalendarTrigger> "@ } "AtStartup" { # Paleisties paleidiklių atveju naudokite Delsa, kad įtrauktumėte atsitiktinį pradžios laiką # Kiekvienas įrenginys bus paleistas nuo 5 iki (5 + RandomDelayHours*60) minučių po paleidimo $maxDelayMinutes = 5 + ($RandomDelayHours * 60) @" <BootTrigger> <Įgalintas>true</Enabled> <delsos>PT5M</ delsos> <RandomDelay>PT${RandomDelayHours}H</RandomDelay> </BootTrigger> "@ } }
$scheduledTaskXML = @" <?xml version="1.0" encoding="UTF-16"?> <Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> <RegistrationInfo> <aprašo>renka įmonės surašymo saugiosios įkrovos įvykio duomenis</description> <autoriaus>įmonės saugos</ autoriaus> </RegistrationInfo> <paleidiklių> $taskTrigger </ paleidiklių> <principals> <Principal id="Author"> <UserId>S-1-5-18</UserId> <RunLevel>HighestAvailable</RunLevel> </Pagrindinis> </Principals> <parametrų> <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy> <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries> <StopIfGoingOnBatteries>klaidingas</StopIfGoingOnBatteries> <AllowHardTerminate>true</AllowHardTerminate> <PradėtiKas galima>true</StartWhenAvailable> <RunOnlyIfNetworkAvailable>true</RunOnlyIfNetworkAvailable> <IdleSettings> <StopOnIdleEnd>false</StopOnIdleEnd> <RestartOnIdle>false</RestartOnIdle> </IdleSettings> <AllowStartOnDemand>true</AllowStartOnDemand> <Įgalintas>teisingas</ įgalintas> <paslėptas>klaidingas</paslėptas> <RunOnlyIfIdle>false</RunOnlyIfIdle> <DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession> <UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine> <WakeToRun>false</WakeToRun> <ExecutionTimeLimit>PT1H</ExecutionTimeLimit> <Priority>7</Priority> </ parametrų> <Actions Context="Author"> <Exec> <Command>powershell.exe</Command> <argumentai>-NoProfile -ExecutionPolicy Bypass - File "$wrapperPath"</Arguments> </Exec> </Actions> </ užduočių> " @
# Save task XML to SYSVOL for reference/backup $taskXmlPath = Join-Path $sysvolScriptPath "SecureBootCollection-Task.xml" $scheduledTaskXML | Out-File -FilePath $taskXmlPath -Encoding Unicode -Force Write-Host " Įrašytos suplanuotos užduoties XML į SYSVOL (atsarginė kopija)" -Priekinio planopalva Žalia
# Inject scheduled task into GPO Preferences Write-Host " Scheduleding scheduled task into GPO Preferences..." -ForegroundColor Cyan
$gpoId = $gpo.Id.ToString() $gpoPrefPath = "\\$DomainName\SYSVOL\$DomainName\Policies\{$gpoId}\Machine\Preferences\ScheduledTasks"
# Create Preferences folder structure jei (-not (testo kelias $gpoPrefPath)) { New-Item -ItemType katalogas - Kelias $gpoPrefPath -Force | Nu neapibrėžta reikšmė (Out-Null) }
# Generate unique GUID for the task $taskGuid = [guid]::NewGuid(). ToString("B"). Priseku()
# Build GPO Preferences ScheduledTasks.xml format # Tai skiriasi nuo standartinio užduočių planuoklės XML – tai GPP formatas $gppScheduledTasksXml = @" <?xml version="1.0" encoding="utf-8"?> <ScheduledTasks clsid="{CC63F200-7309-4ba0-B154-A71CD118DBCC}"> <TaskV2 clsid="{D8896631-B747-47a7-84A6-C155337F3BC8}" name="SecureBoot-EventCollection" image="0" changed="$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" uid="$taskGuid" userContext="0" removePolicy="0"> <Properties action="C" name="SecureBoot-EventCollection" runAs="NT AUTHORITY\System" logonType="S4U"> <Task version="1.3"> <RegistrationInfo> <autoriaus>įmonės saugos</ autoriaus> <aprašo>renka apsaugotos įkrovos sertifikato būseną, skirtą įmonės atitikties stebėjimui</aprašo> </RegistrationInfo> <principals> <Principal id="Author"> <UserId>NT AUTHORITY\System</UserId> <LogonType>S4U</LogonType> <RunLevel>HighestAvailable</RunLevel> </Principal> </Principals> parametrų>< <IdleSettings> <trukmė>PT10M</ trukmės> <WaitTimeout>PT1H</WaitTimeout> <StopOnIdleEnd>false</StopOnIdleEnd> <RestartOnIdle>false</RestartOnIdle> </IdleSettings> <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy> <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries> <StopIfGoingOnBatteries>klaidingas</StopIfGoingOnBatteries> <AllowHardTerminate>true</AllowHardTerminate> <PradėtiKasgalima>true</StartWhenAvailable> <RunOnlyIfNetworkAvailable>true</RunOnlyIfNetworkAvailable> <AllowStartOnDemand>true</AllowStartOnDemand> <Įgalintas>true</Enabled> <paslėptas>klaidingas</paslėptas> <RunOnlyIfIdle>false</RunOnlyIfIdle> <WakeToRun>false</WakeToRun> <ExecutionTimeLimit>PT1H</ExecutionTimeLimit> <priority>7</Priority> </ parametrų> <paleidikliai> $taskTrigger </Triggers> <Actions Context="Author"> <Exec> <Command>powershell.exe</Command> <argumentai>-NoProfile -ExecutionPolicy Bypass - File "$wrapperPath"</Arguments> </Exec> </Actions> </ užduočių> <apgyvendinimo įstaigos> </TaskV2> </ScheduledTasks> " @
# Write GPP ScheduledTasks.xml to GPO $gppXmlPath = Join-Path $gpoPrefPath "ScheduledTasks.xml" $gppScheduledTasksXml | Out-File -FilePath $gppXmlPath -Encoding UTF8 -Force Write-Host " [Gerai] Suplanuota užduotis, suleista į GPO" -Priekinio planopalva Žalia Write-Host " Užduočių tvarkaraštis: $Schedule $ScheduleTime su $RandomDelayHours val. atsitiktine delsa" -Priekinio planopalva pilka
# Step 5: Link GPO to OU(s) Write-Host "'n[5/6] Linking GPO to OU(s)..." -ForegroundColor Yellow
$linkedCount = 0 $skippedCount = 0
foreach ($targetOU in $OUPath) { $existingLink = Get-GPInheritance -Target $targetOU -Domain $DomainName | Select-Object -ExpandProperty GpoLinks | Where-Object { $_. DisplayName -eq $GPOName }
if (-not $existingLink) { New-GPLink -Name $GPOName -Target $targetOU -Domain $DomainName -LinkEnabled Taip | Nu neapibrėžta reikšmė (Out-Null) Write-Host " [Gerai] Susieta su: $targetOU" -Priekinio planopalva Žalia $linkedCount++ } dar { Write-Host – jau susieta: $targetOU" -Priekinio planopalva Geltona $skippedCount++ } }
Write-Host "`n Summary: $linkedCount new links, $skippedCount already existed" -ForegroundColor Cyan
# Step 6: Create WMI Filter (optional - for Windows 10/11 only) Write-Host "'n[6/6] Kuriamas WMI filtras..." -Priekinio planopalva Geltona
$wmiFilterName = "Windows 10 and 11 Workstations" $wmiQuery = 'SELECT * FROM Win32_OperatingSystem WHERE Version LIKE "10.%" AND ProductType = "1"'
Write-Host @" [PASTABA] PASIRINKTINAI: WMI filtro kūrimas GPMC Filtro pavadinimas: $wmiFilterName Užklausa: $wmiQuery Tai filtruoja GPO, kad jis būtų taikomas tik Windows 10/11 darbo stotims.
"@ -ForegroundColor Yellow
# Summary Write-Host "'n============================================" -ForegroundColor Cyan Write-Host "DEPLOYMENT COMPLETE" –ForegroundColor Green Write-Host ============================================ - ForegroundColor Cyan Write-Host @"
Summary: - GPO pavadinimas: $GPOName - Paskirties OU: $OUPath - Kolekcijos bendrinimas: $CollectionSharePath - Scenarijaus vieta: $sysvolScriptPath - Tvarkaraštis: $Schedule $ScheduleTime
Next Steps: 1. Kurkite rinkinio bendrinimą naudodami reikiamas teises: - Bendrinimas: $CollectionSharePath - Teisės: domenų kompiuteriai (rašyti), domeno administratoriai (visi)
2. Complete the scheduled task configuration in GPMC (see instructions above)
3. Run 'gpupdate /force' on a test machine to verify deployment
4. Monitor collection results in: $CollectionSharePath
5. Run aggregation script to generate reports: .\Aggregate-SecureBootData.ps1 -InputPath "$CollectionSharePath"
"@ -ForegroundColor White