Deploy Elastic Agent 8.3.2 via Windows GPO

Hi,

The following is a working PowerShell script to deploy Elastic Agent to Windows workstations via Group Policy 'Startup Script'. Group Policy service by default does not include the permission for it to create SymLinks so the PowerShell script adds this privilege to those requested when starting scripts.

Creates HKLM\SOFTWARE\Admin_Scripts\ElasticAgent when installed, to avoid constantly recopying files.

GPO settings are as simple as it gets:
image

I prefer placing smaller deployment tools on the replicated netlogon share. The script copies the content to the local workstation and then installs and registers the agent:

# Variables:
$Source       = "\\ad.company.com\netlogon\ElasticAgent\elastic-agent-8.3.2-windows-x86_64"
$Destination  = "$env:temp\ElasticAgent"
$RegistryHive = "HKLM:\\SOFTWARE"
$RegistryKey  = "Admin_Scripts"
$ScriptName   = "ElasticAgent"


# Group Policies are installed via the gpsvc service, extend rights so that it can create symbolic links and install it next time:
$perm = (Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\gpsvc").RequiredPrivileges;
If ($perm -NotContains "SeCreateSymbolicLinkPrivilege") {
	$perm = $perm + "SeCreateSymbolicLinkPrivilege";
	Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\gpsvc" -Name RequiredPrivileges -Value $perm -Type MultiString;
	Exit 1
};


# Make non-terminating errors terminating.
Trap {
	Write-Error $_ -ErrorAction Continue
	Stop-Transcript
	Exit 1
}
$ErrorActionPreference = 'Stop'


function GetAgent {
	If (!(Test-Path "$env:temp\ElasticAgent")) {
		New-Item -Path $env:temp -Name $ScriptName -ItemType "directory" | Out-Null
	}
	Start-Transcript -Path $Destination"\"install_log.txt -Append -IncludeInvocationHeader
	If (!(Test-Path $Source) -Or !(Test-Path $Destination)) { Throw "$Source and/or $Destination folders are invalid." }
	Copy-Item -Path "$Source\*" -Destination $Destination -Recurse -Force
	If (!(Test-Path $Destination"\elastic-agent.exe")) { Throw "Copy failed." }
}


function InstallAgent {
	cd $Destination
	$ErrorActionPreference = 'Continue'
	.\elastic-agent.exe install --force --url=https://elastic-fleet.company.com:8220 --enrollment-token=***************************************** 2>&1 | Out-Default
	if ($LastExitCode -ne 0) { Throw "Installation failed." }
	$ErrorActionPreference = 'Stop'
	cd ..
	Start-Sleep -Seconds 5
}


If (Test-Path $RegistryHive"\"$RegistryKey) {
	$reg = Get-Itemproperty -Path $RegistryHive"\"$RegistryKey -Name $ScriptName -ErrorAction SilentlyContinue
}
If (!($reg)) {
	GetAgent
	InstallAgent
	If (!(Test-Path $RegistryHive"\"$RegistryKey)) {
		New-Item -Path $RegistryHive -Name $RegistryKey | Out-Null
	}
	New-ItemProperty -Path $RegistryHive"\"$RegistryKey -Name $ScriptName -Value "1" -PropertyType "DWord" -Force | Out-Null
	Stop-Transcript
	Remove-Item -Force -Recurse $Destination
}
Exit 0

Kept stumbling in to the following post which provided the base structure of the script I hacked together: