Kopier og lim inn dette eksempelskriptet og endre etter behov for miljøet:
<# . SYNOPSIS GPO-distribusjonsskript for sikker oppstartshendelsessamling Oppretter og kobler et gruppepolicyobjekt for å distribuere samlingsskriptet som en planlagt oppgave
.DESCRIPTION Dette skriptet automatiserer distribusjonen av hendelsessamlingen sikker oppstart via gruppepolicy.Det oppretter et gruppepolicyobjekt med: - En planlagt oppgave som kjører samlingsskriptet daglig – Riktige tillatelser for skriving til den sentrale delingen – WMI-filtre for å målrette mot bestemte OS-versjoner
.PARAMETER GPOName Navn på det nye gruppepolicyobjektet
.PARAMETER DomainName FQDN for måldomene
.PARAMETER OUPath Unikt navn på OU(e) som GPO skal kobles til.Godtar flere OU-er som en matrise. Ikke nødvendig hvis -AutoDetectOU er angitt.
.PARAMETER AutoDetectOU Bytt til en interaktiv liste, og velg OUs fra Active Directory.Når angitt, er -OUPath valgfritt.
.PARAMETER CollectionSharePath UNC-bane der samlingsresultater lagres
.PARAMETER ScriptSourcePath Bane der samlingsskriptet lagres (kopieres til SYSVOL)
.PARAMETER RandomDelayHours Antall timer skriptkjøring skal spres tilfeldig på tvers av endepunkter.Dette hindrer at alle maskiner skriver til delingen samtidig.Standard: 4 timer. Gyldig område: 1–24 timer. Anbefalte verdier: – 1–10 000 enheter: 4 timer (standard) - 10K-50K-enheter: 8 timer - 50K + enheter: 12-24 timer
.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 Viser alle OUs i domenet og ber om valg.
.EXAMPLE .\Deploy-GPO-SecureBootCollection.ps1 -DomainName "contoso.com" -OUPath @("OU=Workstations,DC=contoso,DC=com", "OU=Laptops,DC=contoso,DC=com") Kobler gruppepolicyobjekt til flere OU-er i én enkelt kjøring.
.NOTES Krever: Active Directory PowerShell-modulen, gruppepolicy-modulen Må kjøres med domene Admin eller delegerte opprettelsesrettigheter for gruppepolicyobjekter #>
[CmdletBinding()] param( [Parameter(Obligatorisk = $false)] [string]$GPOName = "SecureBoot-EventCollection", [Parameter(Obligatorisk = $false)] [streng]$DomainName, [Parameter(Obligatorisk = $false)] [string[]]$OUPath, [Parameter(Obligatorisk = $false)] [switch]$AutoDetectOU, [Parameter(Obligatorisk = $false)] [string]$CollectionSharePath = "\\$DomainName\NETLOGON\SecureBootLogs", [Parameter(Obligatorisk = $false)] [string]$ScriptSourcePath = ".\Detect-SecureBootCertUpdateStatus.ps1", [Parameter(Obligatorisk = $false)] [ValidateSet("Daily", "Weekly", "AtStartup")] [streng]$Schedule = "Daglig", [Parameter(Obligatorisk = $false)] [streng]$ScheduleTime = "14:00", [Parameter(Obligatorisk = $false)] [ValidateRange(1, 24)] [int]$RandomDelayHours = 4 )
#Requires -Modules ActiveDirectory, GroupPolicy #Requires -Versjon 5.1
$ErrorActionPreference = "Stop" $DownloadUrl = "https://aka.ms/getsecureboot" $DownloadSubPage = «Eksempler på distribusjon og overvåking»
# ============================================================================ # AVHENGIGHETSVALIDERING # ============================================================================
function Test-ScriptDependencies { param( [Parameter(Obligatorisk = $true)] [streng]$ScriptDirectory, [Parameter(Obligatorisk = $true)] [string[]]$RequiredScripts ) $missingScripts = @() foreach ($script i $RequiredScripts) { $scriptPath = Join-Path $ScriptDirectory $script if (-not (Test-Path $scriptPath)) { $missingScripts += $script } } hvis ($missingScripts.Count -gt 0) { Write-Host "" Write-Host ("=" * 70) -Forgrunnsfarge rød Write-Host " MISSING DEPENDENCIES" -ForegroundColor Red Write-Host ("=" * 70) -ForegroundColor Red Write-Host "" Write-Host "Følgende nødvendige skript ble ikke funnet:" -ForegroundColor Yellow foreach ($script i $missingScripts) { Write-Host " - $script" -Forgrunnsfarge hvit } Write-Host "" Write-Host «Last ned de nyeste skriptene fra:» –Forgrunnsfarge Cyan URL-adresse for Write-Host : $DownloadUrl" -ForegroundColor White Write-Host " Navigate to: '$DownloadSubPage'" -ForegroundColor White Write-Host "" Write-Host «Trekk ut alle skript i samme mappe og kjør på nytt». –Forgrunnsfarge gul Write-Host "" returner $false } returner $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)) { avslutt 1 }
# ============================================================================ # AUTOMATISK IDENTIFISER DOMENENAVN # ============================================================================
if (-not $DomainName) { $DomainName = $env:USERDNSDOMAIN hvis (-ikke $DomainName) { # Prøv å hente fra AD-modulen prøv { Import-Module ActiveDirectory -ErrorAction-stopp $DomainName = (Get-ADDomain). DNSRoot } catch { Write-Host «FEIL: Finner ikke domenenavn automatisk.» -Forgrunnsfarge rød Write-Host «Angi -DomainName-parameter». -ForegroundColor Yellow Write-Host "" Write-Host "Eksempel:" -Forgrunnsfarge grå Write-Host " .\Deploy-GPO-SecureBootCollection.ps1 -DomainName contoso.com -AutoDetectOU" -ForegroundColor White avslutt 1 } } Write-Host «Automatisk oppdaget domene: $DomainName» –Forgrunnsfarge grønn }
# Set CollectionSharePath default if not explicitly provided hvis (-ikke $PSBoundParameters.ContainsKey('CollectionSharePath')) { $CollectionSharePath = "\\$DomainName\NETLOGON\SecureBootLogs" }
Write-Host "============================================" -ForegroundColor Cyan Write-Host "Secure Boot Collection - GPO Deployment" -ForegroundColor Cyan Write-Host "============================================" -ForegroundColor Cyan
# Validate prerequisites Write-Host "'n[1/6] Validerer forutsetninger..." -Forgrunnsfarge gul
if (-not (Get-Module -ListAvailable -Name ActiveDirectory)) { finner ikke ActiveDirectory-modulen. Installer RSAT-verktøy.» }
if (-not (Get-Module -ListAvailable -Name GroupPolicy)) { finner ikke GroupPolicy-modulen. Installer RSAT-verktøy.» }
Import-Module ActiveDirectory Import-Module GroupPolicy
# Validate domain connectivity prøv { $domain = Get-ADDomain -Server $DomainName Write-Host " Koblet til domene: $($domain. DNSRoot)" -ForegroundColor Green } catch { throw "Cannot connect to domain: $DomainName. Feil: $_" }
# Handle OU selection hvis ($AutoDetectOU) { Write-Host "'n Oppdage OUs i domene..." -Forgrunnsfarge Cyan $allOUs = Get-ADOrganizationalUnit -Filter * -Server $DomainName | Sort-Object DistinguishedName | Select-Object @{N='Index'; E={0}}, Navn, DistinguishedName # Tilordne indekser for ($i = 0; $i -lt $allOUs.Count; $i++) { $allOUs[$i]. Indeks = $i + 1 } Write-Host "'n Tilgjengelige OUs:" -Forgrunnsfarge Gul Write-Host " ---------------------------------------------------------------------" -ForegroundColor DarkGray $allOUs | ForEach-Object { Write-Host (" {0,3}) {1}" -f $_. Indeks, $_. DistinguishedName) -Forgrunnsfarge hvit } Write-Host " ---------------------------------------------------------------------" -ForegroundColor DarkGray Write-Host " Tips: Skriv inn kommadelte tall for å velge flere OUs (f.eks. 1,3,5)" -Forgrunnsfarge DarkGray Write-Host " Enter 'A' to select ALL OUs" -ForegroundColor DarkGray Write-Host "" $selection = Read-Host " Velg OU(r) for å koble GPO" hvis ($selection -eq 'A' -eller $selection -eq 'a') { $OUPath = $allOUs.DistinguishedName Write-Host " Selected ALL $($OUPath.Count) OUs" -ForegroundColor Green } ellers { $indices = $selection -split ',' | ForEach-Object { [int]$_. Trim() } $OUPath = @() foreach ($idx i $indices) { $selected = $allOUs | Where-Object { $_. Indeks -eq $idx } hvis ($selected) { $OUPath += $selected. DistinguishedName } ellers { Write-Warning «Ugyldig indeks: $idx – hopper over» } } } hvis ($OUPath.Count -eq 0) { throw "No OUs selected. Avbrytes.» } Write-Host "'n Selected $($OUPath.Count) OU(s):" -ForegroundColor Green $OUPath | ForEach-Object { Write-Host " - $_" -ForegroundColor Gray } } elseif (-not $OUPath -or $OUPath.Count -eq 0) { throw "Either -OUPath or -AutoDetectOU must be specified." } ellers { # Valider hver OU finnes foreach ($path i $OUPath) { prøv { $ou = Get-ADOrganizationalUnit -Identity $path -Server $DomainName Write-Host " Target OU funnet: $($ou. Name)" -ForegroundColor Green } catch { finner ikke ou: $path } } }
# Validate source script exists if (-not (Test-Path $ScriptSourcePath)) { finner ikke samlingsskript: $ScriptSourcePath }
# Step 2: Create collection share structure Write-Host "'n[2/6] Konfigurerer delt samlingsressurs..." -Forgrunnsfarge gul
$sysvolScriptPath = "\\$DomainName\SYSVOL\$DomainName\Scripts\SecureBootCollection"
# Create SYSVOL script folder if (-not (Test-Path $sysvolScriptPath)) { New-Item -ItemType Directory -Path $sysvolScriptPath -Force | Ut-null Write-Host " Opprettet SYSVOL-skriptmappe: $sysvolScriptPath" -ForegroundColor Green }
# 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) if (Test-Path $destScript -PathType Container) { Remove-Item $destScript -Recurse -Force }
Copy-Item -Path $ScriptSourcePath -Destination $destScript -Force Write-Host " Kopiert samlingsskript til SYSVOL" -ForegroundColor Green
# Create a wrapper script that calls the main script with parameters $wrapperScript = @" # Wrapper for sikker oppstart av hendelsessamling # Automatisk generert av Deploy-GPO-SecureBootCollection.ps1
`$ErrorActionPreference = 'SilentlyContinue'
# Configuration '$CollectionShare = '$CollectionSharePath' '$ScriptPath = '$sysvolScriptPath\Detect-SecureBootCertUpdateStatus.ps1'
# Run collection with -OutputPath parameter hvis (testbanen $ScriptPath) { & $ScriptPath -OutputPath $CollectionShare } ellers { Write-EventLog -LogName Application -Source "SecureBootCollection" -EventId 1001 -EntryType Error -Message "Collection script not found: '$ScriptPath" } " @
$wrapperPath = Join-Path $sysvolScriptPath "Run-SecureBootCollection.ps1" $wrapperScript | Out-File -FilePath $wrapperPath -Koding UTF8 -Force Write-Host " Opprettet wrapper script" -ForegroundColor Green
# Create collection share (if on a file server) Write-Host " Samlingsdelingsbane: $CollectionSharePath" -Forgrunnsfarge Cyan Write-Host " OBS! Kontroller at denne ressursen finnes med "Domain Computers" skrivetilgang" -ForegroundColor Yellow
# Step 3: Create the GPO Write-Host "'n[3/6] Oppretter gruppepolicy objekt..." -Forgrunnsfarge gul
# Check if GPO already exists $existingGPO = Get-GPO -Name $GPOName -Domain $DomainName -ErrorAction SilentlyContinue
if ($existingGPO) { Write-Host finnes allerede $GPOName. Oppdaterer ... -Forgrunnsfarge gul $gpo = $existingGPO } ellers { $gpo = New-GPO -Name $GPOName -Domain $DomainName -Comment "Deploys Secure Boot event collection script to endpoints" Write-Host " Opprettet GPO: $GPOName" -ForegroundColor Green }
# Step 4: Configure Scheduled Task via GPO Preferences Write-Host "'n[4/6] Konfigurerer planlagt oppgave..." -Forgrunnsfarge Gul
# Build the scheduled task XML # RandomDelay sprer kjøring på tvers av endepunkter for å hindre serveroverbelastning Write-Host " Tilfeldig forsinkelse: $RandomDelayHours timer (sprer belastning over flåten)" -Forgrunnsfarge Cyan
$taskTrigger = switch ($Schedule) { "Daglig" { @" ><CalendarTrigger <StartBoundary>2024-01-01T${ScheduleTime}:00</StartBoundary> <aktivert>sann</aktivert> <ScheduleByDay> <DaysInterval>1</DaysInterval> </ScheduleByDay> <RandomDelay>PT${RandomDelayHours}H</RandomDelay> </CalendarTrigger> "@ } "Ukentlig" { @" ><CalendarTrigger <StartBoundary>2024-01-01T${ScheduleTime}:00</StartBoundary> <aktivert>sann</aktivert> <ScheduleByWeek> <WeeksInterval>1</WeeksInterval> <DaysOfWeek> <onsdag /> </DaysOfWeek> </ScheduleByWeek> <RandomDelay>PT${RandomDelayHours}H</RandomDelay> </CalendarTrigger> "@ } "AtStartup" { # For oppstartsutløsere bruker du Forsinkelse til å legge til tilfeldig starttidspunkt # Hver maskin starter mellom 5 og (5 + RandomDelayHours*60) minutter etter oppstart $maxDelayMinutes = 5 + ($RandomDelayHours * 60) @" ><BootTrigger <aktivert>sann</aktivert> <forsinkelse>PT5M</forsinkelse> <RandomDelay>PT${RandomDelayHours}H</RandomDelay> </BootTrigger> "@ } }
$scheduledTaskXML = @" <?xml version="1.0" koding="UTF-16"?> <Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> <RegistrationInfo> <Beskrivelse>samler inn hendelsesdata for sikker oppstart for folketelling for virksomheter</Description> <Author>Enterprise Security</Author> </RegistrationInfo> <utløsere> $taskTrigger </Utløsere> <sikkerhetskontohavere> <principal id="Author"> <UserId>S-1-5-18</UserId> <RunLevel>høyest tilgjengelige</RunLevel> </Principal> </Principals> <innstillinger> <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy> <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries> <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries> <AllowHardTerminate>sann</AllowHardTerminate> <StartWhenAvailable>true</StartWhenAvailable> <RunOnlyIfNetworkAvailable>true</RunOnlyIfNetworkAvailable> <IdleSettings> <StopOnIdleEnd>usann</StopOnIdleEnd> <RestartOnIdle>usann</RestartOnIdle> </IdleSettings> <AllowStartOnDemand>sann</AllowStartOnDemand> <aktivert>sann</aktivert> <skjult>usann</skjult> <RunOnlyIfIdle>usann</RunOnlyIfIdle> <DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession> <UseUnifiedSchedulingEngine>sann</UseUnifiedSchedulingEngine> <WakeToRun>usann</WakeToRun> <ExecutionTimeLimit>PT1H</ExecutionTimeLimit> <prioritet>7</prioritet> </Innstillinger> <Actions Context="Author"> <Exec> <kommando>powershell.exe</kommando> <argumenter>-NoProfile -ExecutionPolicy Bypass -File "$wrapperPath"</Arguments> </Exec> </Actions> </Aktivitet> " @
# 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 " Lagret planlagt XML-oppgave til SYSVOL (sikkerhetskopiering)" -Forgrunnsfarge grønn
# Inject scheduled task into GPO Preferences Write-Host " Sette inn planlagt oppgave i GPO-innstillinger..." -Forgrunnsfarge Cyan
$gpoId = $gpo.Id.ToString() $gpoPrefPath = "\\$DomainName\SYSVOL\$DomainName\Policies\{$gpoId}\Machine\Preferences\ScheduledTasks"
# Create Preferences folder structure if (-not (Test-Path $gpoPrefPath)) { New-Item -ItemType Directory -Path $gpoPrefPath -Force | Ut-null }
# Generate unique GUID for the task $taskGuid = [guid]::NewGuid(). ToString("B"). ToUpper()
# Build GPO Preferences ScheduledTasks.xml format # Dette er forskjellig fra standard XML for oppgaveplanlegging – det er GPP-format $gppScheduledTasksXml = @" <?xml version="1.0" koding="utf-8"?> <ScheduledTasks clsid="{CC63F200-7309-4ba0-B154-A71CD118DBCC}"> <TaskV2 clsid="{D8896631-B747-47a7-84A6-C155337F3BC8}" name="SecureBoot-EventCollection" image="0" endret ="$(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> <Author>Enterprise Security</Author> <Description>samler inn sertifikatstatus for sikker oppstart for overvåking av samsvar for bedrifter</Description> </RegistrationInfo> <hovedkontohavere> <principal id="Author"> <UserId>NT AUTHORITY\System</UserId> <LogonType>S4U</LogonType> <RunLevel>høyest tilgjengelige</RunLevel> </Principal> </Principals> <innstillinger> <IdleSettings> <varighet>PT10M</duration> <WaitTimeout>PT1H</WaitTimeout> <StopOnIdleEnd>usann</StopOnIdleEnd> <RestartOnIdle>usann</RestartOnIdle> </IdleSettings> <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy> <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries> <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries> <AllowHardTerminate>sann</AllowHardTerminate> <StartWhenAvailable>true</StartWhenAvailable> <RunOnlyIfNetworkAvailable>true</RunOnlyIfNetworkAvailable> <AllowStartOnDemand>sann</AllowStartOnDemand> <aktivert>sann</aktivert> <skjult>usann</skjult> <RunOnlyIfIdle>usann</RunOnlyIfIdle> <WakeToRun>false</WakeToRun> <ExecutionTimeLimit>PT1H</ExecutionTimeLimit> <prioritet>7</prioritet> </Innstillinger> <utløsere> $taskTrigger </Utløsere> <Actions Context="Author"> <Exec> <kommando>powershell.exe</kommando> <argumenter>-NoProfile -ExecutionPolicy Bypass -File "$wrapperPath"</Arguments> </Exec> </Actions> </> </Properties> </TaskV2> </ScheduledTasks> " @
# Write GPP ScheduledTasks.xml to GPO $gppXmlPath = Join-Path $gpoPrefPath "ScheduledTasks.xml" $gppScheduledTasksXml | Out-File -FilePath $gppXmlPath -Koding UTF8 -Force Write-Host " [OK] Planlagt oppgave satt inn i GPO" -ForegroundColor Green Write-Host " Aktivitetsplan: $Schedule på $ScheduleTime med $RandomDelayHours time tilfeldig forsinkelse" -Forgrunnsfarge grå
# Step 5: Link GPO to OU(s) Write-Host "'n[5/6] Kobler gruppepolicyobjekt til OU(er)..." -Forgrunnsfarge gul
$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 Yes | Ut-null Write-Host " [OK] Koblet til: $targetOU" -Forgrunnsfarge grønn $linkedCount++ } ellers { Write-Host " - Allerede koblet: $targetOU" -Forgrunnsfarge gul $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] Oppretter WMI-filter..." -Forgrunnsfarge gul
$wmiFilterName = "Windows 10 and 11 Workstations" $wmiQuery = 'SELECT * FROM Win32_OperatingSystem WHERE version LIKE "10.%" AND ProductType = "1"'
Write-Host @" [OBS! VALGFRITT: Opprett WMI-filter i GPMC Filternavn: $wmiFilterName Spørring: $wmiQuery Dette filtrerer gruppepolicyobjektet slik at det bare gjelder for Windows 10/11 arbeidsstasjoner.
"@ -ForegroundColor Yellow
# Summary Write-Host "'n============================================" -ForegroundColor Cyan Write-Host «DEPLOYMENT COMPLETE» –Forgrunnsfarge grønn Write-Host "============================================" -ForegroundColor Cyan Write-Host @»
Summary: - Navn på gruppepolicyobjekt: $GPOName - Mål ou: $OUPath - Samlingsdeling: $CollectionSharePath - Skriptplassering: $sysvolScriptPath - Planlegg: $Schedule på $ScheduleTime
Next Steps: 1. Opprett samlingsdelingen med riktige tillatelser: - Del: $CollectionSharePath - Tillatelser: Domenedatamaskiner (skrive), domeneadministratorer (fullstendig)
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