$ErrorActionPreference = "Stop" Set-Location $PSScriptRoot if (-not (Get-Command docker -ErrorAction SilentlyContinue)) { throw "Docker fehlt." } docker compose version | Out-Null function Hex([int]$bytes) { $b = New-Object byte[] $bytes; [Security.Cryptography.RandomNumberGenerator]::Fill($b); return ([BitConverter]::ToString($b)).Replace("-","").ToLower() } if (-not (Test-Path .env)) { $presetEnrollment = $env:ENROLLMENT_KEY $enrollment = if ([string]::IsNullOrWhiteSpace($presetEnrollment)) { Hex 32 } else { $presetEnrollment } $vals = @{ POSTGRES_PASSWORD=Hex 24; CLICKHOUSE_PASSWORD=Hex 24; ENROLLMENT_KEY=$enrollment; UI_PASSWORD=Hex 18; GARAGE_ACCESS_KEY="GK$(Hex 16)"; GARAGE_SECRET_KEY=Hex 32; GARAGE_RPC_SECRET=Hex 32; GARAGE_ADMIN_TOKEN=Hex 32; GARAGE_METRICS_TOKEN=Hex 32 } @" INGRESS_BIND=0.0.0.0 INGRESS_PORT=8090 UI_BIND=0.0.0.0 UI_PORT=8080 TENANT_ID=default UI_USERNAME=admin UI_PASSWORD=$($vals.UI_PASSWORD) POSTGRES_PASSWORD=$($vals.POSTGRES_PASSWORD) CLICKHOUSE_PASSWORD=$($vals.CLICKHOUSE_PASSWORD) ENROLLMENT_KEY=$($vals.ENROLLMENT_KEY) GARAGE_ACCESS_KEY=$($vals.GARAGE_ACCESS_KEY) GARAGE_SECRET_KEY=$($vals.GARAGE_SECRET_KEY) GARAGE_RPC_SECRET=$($vals.GARAGE_RPC_SECRET) GARAGE_ADMIN_TOKEN=$($vals.GARAGE_ADMIN_TOKEN) GARAGE_METRICS_TOKEN=$($vals.GARAGE_METRICS_TOKEN) GARAGE_BUCKET=siem-raw EVENT_RETENTION_DAYS=90 ROLLUP_RETENTION_DAYS=730 RAW_RETENTION=720h RAW_ARCHIVE_ENABLED=true KAFKA_RETENTION_MS=86400000 KAFKA_PARTITIONS=6 DETECTOR_INTERVAL=30s DETECTOR_LOOKBACK=20m UI_QUERY_LIMIT=500 "@ | Set-Content .env } $envMap=@{}; Get-Content .env | ForEach-Object { if ($_ -match '^([^#=]+)=(.*)$') {$envMap[$matches[1]]=$matches[2]} } if (-not $envMap.ContainsKey('UI_USERNAME')) { $envMap['UI_USERNAME']='admin'; Add-Content .env "UI_USERNAME=admin" } if (-not $envMap.ContainsKey('UI_PASSWORD') -or [string]::IsNullOrWhiteSpace($envMap['UI_PASSWORD'])) { $envMap['UI_PASSWORD']=Hex 18; Add-Content .env "UI_PASSWORD=$($envMap.UI_PASSWORD)" } (Get-Content deploy/garage/garage.toml.template -Raw).Replace('__GARAGE_RPC_SECRET__',$envMap.GARAGE_RPC_SECRET).Replace('__GARAGE_ADMIN_TOKEN__',$envMap.GARAGE_ADMIN_TOKEN).Replace('__GARAGE_METRICS_TOKEN__',$envMap.GARAGE_METRICS_TOKEN) | Set-Content deploy/garage/garage.toml (Get-Content deploy/clickhouse/init.sql.template -Raw).Replace('__EVENT_RETENTION_DAYS__',$envMap.EVENT_RETENTION_DAYS).Replace('__ROLLUP_RETENTION_DAYS__',$envMap.ROLLUP_RETENTION_DAYS) | Set-Content deploy/clickhouse/init.sql Write-Host "Baue und starte Greenfield SIEM ..." docker compose build --pull docker compose up -d --remove-orphans Write-Host "Pruefe Dienste ..." $healthy = $false for ($i = 0; $i -lt 60; $i++) { try { Invoke-WebRequest -UseBasicParsing -TimeoutSec 2 "http://127.0.0.1:$($envMap.UI_PORT)/readyz" | Out-Null Invoke-WebRequest -UseBasicParsing -TimeoutSec 2 "http://127.0.0.1:$($envMap.INGRESS_PORT)/readyz" | Out-Null $healthy = $true break } catch { Start-Sleep -Seconds 2 } } if (-not $healthy) { throw "Deployment gestartet, Healthcheck noch nicht gruen. Pruefe: docker compose ps; docker compose logs" } Write-Host "" Write-Host "Greenfield SIEM laeuft." Write-Host "UI: http://127.0.0.1:$($envMap.UI_PORT)/ui" Write-Host "Ingress: http://127.0.0.1:$($envMap.INGRESS_PORT)/ingest" Write-Host "UI-Login: $($envMap.UI_USERNAME) / $($envMap.UI_PASSWORD)" Write-Host "Enrollment-Key: $($envMap.ENROLLMENT_KEY)" Write-Host "Secrets stehen in .env (Datei schuetzen und sichern)."