255 lines
12 KiB
Cheetah
255 lines
12 KiB
Cheetah
# RedFlag Agent Installer - Windows PowerShell
|
|
# Generated for agent: {{.AgentID}}
|
|
# Platform: {{.Platform}}
|
|
# Architecture: {{.Architecture}}
|
|
# Version: {{.Version}}
|
|
|
|
param(
|
|
[Parameter(Mandatory=$false)]
|
|
[switch]$SkipServiceInstall = $false
|
|
)
|
|
|
|
$AgentID = "{{.AgentID}}"
|
|
$BinaryURL = "{{.BinaryURL}}"
|
|
$ConfigURL = "{{.ConfigURL}}"
|
|
$InstallDir = "C:\Program Files\RedFlag"
|
|
$ConfigDir = "C:\ProgramData\RedFlag"
|
|
$OldConfigDir = "C:\ProgramData\Aggregator"
|
|
$ServiceName = "RedFlagAgent"
|
|
$Version = "{{.Version}}"
|
|
$Timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
|
|
$BackupDir = Join-Path $ConfigDir "backups\backup.$Timestamp"
|
|
|
|
Write-Host "=== RedFlag Agent v$Version Installation ===" -ForegroundColor Cyan
|
|
Write-Host "Agent ID: $AgentID"
|
|
Write-Host "Platform: {{.Platform}}"
|
|
Write-Host "Installing to: $InstallDir\redflag-agent.exe"
|
|
Write-Host
|
|
|
|
# Step 0: Detect existing installation and migration requirements
|
|
Write-Host "Detecting existing RedFlag installations..." -ForegroundColor Yellow
|
|
$MigrationNeeded = $false
|
|
$CurrentVersion = "unknown"
|
|
$ConfigVersion = "0"
|
|
$ConfigPath = Join-Path $ConfigDir "config.json"
|
|
$OldConfigPath = Join-Path $OldConfigDir "config.json"
|
|
|
|
# Check for existing installation in new location
|
|
if (Test-Path $ConfigPath) {
|
|
Write-Host "✓ Existing installation detected at $ConfigDir" -ForegroundColor Green
|
|
try {
|
|
$Config = Get-Content $ConfigPath | ConvertFrom-Json
|
|
if ($Config.agent_version) { $CurrentVersion = $Config.agent_version }
|
|
if ($Config.version) { $ConfigVersion = $Config.version.ToString() }
|
|
} catch {
|
|
Write-Host " Warning: Could not parse config.json" -ForegroundColor Yellow
|
|
}
|
|
Write-Host " Current agent version: $CurrentVersion"
|
|
Write-Host " Current config version: $ConfigVersion"
|
|
} elseif (Test-Path $OldConfigPath) {
|
|
Write-Host "⚠ Old installation detected at $OldConfigDir - MIGRATION REQUIRED" -ForegroundColor Yellow
|
|
$MigrationNeeded = $true
|
|
try {
|
|
$Config = Get-Content $OldConfigPath | ConvertFrom-Json
|
|
if ($Config.agent_version) { $CurrentVersion = $Config.agent_version }
|
|
if ($Config.version) { $ConfigVersion = $Config.version.ToString() }
|
|
} catch {
|
|
Write-Host " Warning: Could not parse config.json" -ForegroundColor Yellow
|
|
}
|
|
Write-Host " Current agent version: $CurrentVersion"
|
|
Write-Host " Current config version: $ConfigVersion"
|
|
} else {
|
|
Write-Host "✓ Fresh installation" -ForegroundColor Green
|
|
}
|
|
|
|
# Determine if migration is needed
|
|
if (-not $MigrationNeeded) {
|
|
# Check if config version indicates migration is needed
|
|
try {
|
|
if ([int]$ConfigVersion -lt 4) {
|
|
$MigrationNeeded = $true
|
|
Write-Host "⚠ Config version $ConfigVersion < v4 - migration required" -ForegroundColor Yellow
|
|
}
|
|
} catch {
|
|
# Config version not a valid number
|
|
}
|
|
|
|
# Check for missing security features
|
|
if (Test-Path $ConfigPath) {
|
|
$ConfigContent = Get-Content $ConfigPath -Raw
|
|
if ($ConfigContent -notmatch "nonce_validation") {
|
|
$MigrationNeeded = $true
|
|
Write-Host "⚠ Missing security feature: nonce_validation" -ForegroundColor Yellow
|
|
}
|
|
if ($ConfigContent -notmatch "machine_id") {
|
|
$MigrationNeeded = $true
|
|
Write-Host "⚠ Missing security feature: machine_id_binding" -ForegroundColor Yellow
|
|
}
|
|
}
|
|
}
|
|
|
|
# Handle migration if needed
|
|
if ($MigrationNeeded) {
|
|
Write-Host
|
|
Write-Host "=== Migration Required ===" -ForegroundColor Cyan
|
|
Write-Host "Agent will migrate on first start. Backing up configuration..." -ForegroundColor Yellow
|
|
|
|
# Create backup directory
|
|
New-Item -ItemType Directory -Force -Path $BackupDir | Out-Null
|
|
|
|
# Backup old configuration if it exists
|
|
if (Test-Path $OldConfigPath) {
|
|
Write-Host "Backing up old configuration..." -ForegroundColor Yellow
|
|
Copy-Item $OldConfigPath $BackupDir -ErrorAction SilentlyContinue
|
|
}
|
|
|
|
# Backup current configuration if we're upgrading
|
|
if (Test-Path $ConfigPath) {
|
|
Write-Host "Backing up current configuration..." -ForegroundColor Yellow
|
|
Copy-Item $ConfigPath "$BackupDir\config.json.backup" -ErrorAction SilentlyContinue
|
|
}
|
|
|
|
Write-Host "Migration will run automatically when agent starts."
|
|
Write-Host "View migration logs with: Get-EventLog -LogName Application -Source $ServiceName -Newest 50"
|
|
Write-Host
|
|
}
|
|
|
|
# Step 1: Stop existing service if running
|
|
$Service = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
|
|
if ($Service -and $Service.Status -eq 'Running') {
|
|
Write-Host "Stopping existing RedFlag agent service..." -ForegroundColor Yellow
|
|
Stop-Service -Name $ServiceName -Force
|
|
Start-Sleep -Seconds 2
|
|
}
|
|
|
|
# Step 2: Create directories
|
|
Write-Host "Creating directories..." -ForegroundColor Yellow
|
|
New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
|
|
New-Item -ItemType Directory -Force -Path $ConfigDir | Out-Null
|
|
New-Item -ItemType Directory -Force -Path "$ConfigDir\backups" | Out-Null
|
|
New-Item -ItemType Directory -Force -Path "$ConfigDir\state" | Out-Null
|
|
New-Item -ItemType Directory -Force -Path "$ConfigDir\logs" | Out-Null
|
|
|
|
# Step 3: Download agent binary
|
|
Write-Host "Downloading agent binary..." -ForegroundColor Yellow
|
|
$BinaryPath = Join-Path $InstallDir "redflag-agent.exe"
|
|
Invoke-WebRequest -Uri $BinaryURL -OutFile $BinaryPath -UseBasicParsing
|
|
|
|
# Step 4: Handle configuration
|
|
$ConfigPath = Join-Path $ConfigDir "config.json"
|
|
if (Test-Path $ConfigPath) {
|
|
# Upgrade - preserve existing config
|
|
Write-Host "Upgrade detected - preserving existing configuration" -ForegroundColor Green
|
|
Write-Host "Agent will handle migration automatically on first start" -ForegroundColor Green
|
|
} else {
|
|
# Fresh install - create minimal config template with registration token
|
|
Write-Host "Fresh install detected - creating minimal configuration template" -ForegroundColor Green
|
|
|
|
$ConfigTemplate = @"
|
|
{
|
|
"version": 5,
|
|
"agent_version": "$Version",
|
|
"agent_id": "",
|
|
"token": "",
|
|
"refresh_token": "",
|
|
"registration_token": "{{.RegistrationToken}}",
|
|
"machine_id": "",
|
|
"check_in_interval": 300,
|
|
"server_url": "{{.ServerURL}}",
|
|
"network": {
|
|
"timeout": 30000000000,
|
|
"retry_count": 3,
|
|
"retry_delay": 5000000000,
|
|
"max_idle_conn": 10
|
|
},
|
|
"proxy": {
|
|
"enabled": false
|
|
},
|
|
"tls": {
|
|
"enabled": false,
|
|
"insecure_skip_verify": false
|
|
},
|
|
"logging": {
|
|
"level": "info",
|
|
"max_size": 100,
|
|
"max_backups": 3,
|
|
"max_age": 28
|
|
},
|
|
"subsystems": {
|
|
"system": {"enabled": true, "timeout": 10000000000, "circuit_breaker": {"enabled": true, "failure_threshold": 3, "failure_window": 600000000000, "open_duration": 1800000000000, "half_open_attempts": 2}},
|
|
"filesystem": {"enabled": true, "timeout": 10000000000, "circuit_breaker": {"enabled": true, "failure_threshold": 3, "failure_window": 600000000000, "open_duration": 1800000000000, "half_open_attempts": 2}},
|
|
"network": {"enabled": true, "timeout": 30000000000, "circuit_breaker": {"enabled": true, "failure_threshold": 3, "failure_window": 600000000000, "open_duration": 1800000000000, "half_open_attempts": 2}},
|
|
"processes": {"enabled": true, "timeout": 30000000000, "circuit_breaker": {"enabled": true, "failure_threshold": 3, "failure_window": 600000000000, "open_duration": 1800000000000, "half_open_attempts": 2}},
|
|
"updates": {"enabled": true, "timeout": 30000000000, "circuit_breaker": {"enabled": false, "failure_threshold": 0, "failure_window": 0, "open_duration": 0, "half_open_attempts": 0}},
|
|
"storage": {"enabled": true, "timeout": 10000000000, "circuit_breaker": {"enabled": true, "failure_threshold": 3, "failure_window": 600000000000, "open_duration": 1800000000000, "half_open_attempts": 2}}
|
|
},
|
|
"security": {
|
|
"ed25519_verification": true,
|
|
"nonce_validation": true,
|
|
"machine_id_binding": true
|
|
}
|
|
}
|
|
"@
|
|
|
|
$ConfigTemplate | Set-Content -Path $ConfigPath -Encoding UTF8
|
|
}
|
|
|
|
# Step 5: Set permissions
|
|
Write-Host "Setting file permissions..." -ForegroundColor Yellow
|
|
icacls $ConfigPath /inheritance:r /grant:r "SYSTEM:(OI)(CI)F" /grant:r "Administrators:(OI)(CI)F" | Out-Null
|
|
|
|
# Register agent with server (if token provided)
|
|
if ("{{.RegistrationToken}}" -ne "") {
|
|
Write-Host "[INFO] [installer] [register] Registering agent with server..." -ForegroundColor Cyan
|
|
$AgentBinary = if ($AgentPath) { "$AgentPath" } else { "$AgentDir\redflag-agent.exe" }
|
|
$RegisterProcess = Start-Process -FilePath $AgentBinary -ArgumentList "--server", "{{.ServerURL}}", "--token", "{{.RegistrationToken}}", "--register" -Wait -PassThru -NoNewWindow
|
|
if ($RegisterProcess.ExitCode -eq 0) {
|
|
Write-Host "[SUCCESS] [installer] [register] Agent registered successfully" -ForegroundColor Green
|
|
Write-Host "[INFO] [installer] [register] Agent ID assigned, configuration updated" -ForegroundColor Gray
|
|
} else {
|
|
Write-Host "[ERROR] [installer] [register] Registration failed - check token validity and server connectivity" -ForegroundColor Red
|
|
Write-Host "[WARN] [installer] [register] Agent installed but not registered. Service will not start." -ForegroundColor Yellow
|
|
Write-Host ""
|
|
Write-Host "[INFO] [installer] [register] To retry registration manually:" -ForegroundColor Gray
|
|
Write-Host "[INFO] [installer] [register] $AgentBinary --server {{.ServerURL}} --token YOUR_TOKEN --register" -ForegroundColor Gray
|
|
Write-Host "[INFO] [installer] [register] Then start service:" -ForegroundColor Gray
|
|
Write-Host "[INFO] [installer] [register] Start-Service -Name $ServiceName" -ForegroundColor Gray
|
|
exit 1
|
|
}
|
|
} else {
|
|
Write-Host "[INFO] [installer] [register] No registration token provided - skipping registration" -ForegroundColor Gray
|
|
Write-Host "[INFO] [installer] [register] Service will start but agent will exit until registered" -ForegroundColor Gray
|
|
Write-Host "[INFO] [installer] [register] To register manually:" -ForegroundColor Gray
|
|
Write-Host "[INFO] [installer] [register] $AgentBinary --server {{.ServerURL}} --token YOUR_TOKEN --register" -ForegroundColor Gray
|
|
}
|
|
|
|
# Step 6: Install Windows service (if not skipped)
|
|
if (-not $SkipServiceInstall) {
|
|
Write-Host "Creating Windows service..." -ForegroundColor Yellow
|
|
|
|
# Check if service exists and remove it first
|
|
$ExistingService = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
|
|
if ($ExistingService) {
|
|
Stop-Service -Name $ServiceName -Force -ErrorAction SilentlyContinue
|
|
Start-Sleep -Seconds 1
|
|
& sc.exe delete $ServiceName | Out-Null
|
|
}
|
|
|
|
# Register service with appropriate credentials
|
|
if ([System.Environment]::OSVersion.Version.Major -ge 10) {
|
|
# Windows 10/Server 2016+ - can use LocalService
|
|
New-Service -Name $ServiceName -BinaryPathName $BinaryPath -DisplayName "RedFlag Security Agent" -Description "RedFlag Security Monitoring Agent" -StartupType Automatic | Out-Null
|
|
} else {
|
|
# Older Windows - use LocalSystem
|
|
New-Service -Name $ServiceName -BinaryPathName $BinaryPath -DisplayName "RedFlag Security Agent" -Description "RedFlag Security Monitoring Agent" -StartupType Automatic | Out-Null
|
|
}
|
|
|
|
Write-Host "Starting service..." -ForegroundColor Yellow
|
|
Start-Service -Name $ServiceName
|
|
}
|
|
|
|
Write-Host
|
|
Write-Host "✓ Installation complete!" -ForegroundColor Green
|
|
Write-Host "Agent is running. Check status with: Get-Service $ServiceName"
|
|
Write-Host "View logs with: Get-Content $ConfigDir\logs\agent.log -Tail 100 -Wait"
|