Files
edgeguard-native/cmd/edgeguard-ctl/render.go
Debian 5f92851a96 feat(radius): RADIUS-Server via FreeRADIUS (PAP/CHAP) — v1.2.93
Files-basierter RADIUS-Server (Clients + Users), managed analog DHCP/WireGuard.
- Migration 0042: radius_settings (singleton, node-lokal), radius_clients (secret_enc), radius_users (password_enc) — Secrets via secrets.Box verschlüsselt.
- internal/freeradius: Multi-File-Renderer (clients.conf + authorize) via Box.Open, Secret-Escaping (" \), Service default-off/an enabled gekoppelt. internal/services/radius + internal/handlers/radius.go: Settings + Client/User-CRUD, write-only Secret-Semantik, Validierung (IP/CIDR, name-charset), GET liefert secret_configured statt Secret.
- Firewall: udp 1812/1813 Auto-Rule bei enabled. Cluster: clients/users repliziert (hashSpec), radius_settings node-lokal.
- main.go + render.go + WithAllReloaders. Packaging: freeradius Dependency, setgid-Dir /etc/edgeguard/freeradius (Gruppe freeradius), Symlinks clients.conf+authorize, disable-on-install, sudoers.
- UI: RADIUS-Seite (Einstellungen + Clients + Benutzer) unter Sicherheit, Route/Nav/i18n de/en.
- Tests (guarded): Renderer-Inhalt + Secret-Escaping/Roundtrip + Masking. Scope v1: PAP/CHAP files-based (kein EAP/802.1X).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 19:46:42 +02:00

94 lines
2.8 KiB
Go

package main
import (
"context"
"fmt"
"os"
"strings"
"time"
"git.netcell-it.de/projekte/edgeguard-native/internal/chrony"
"git.netcell-it.de/projekte/edgeguard-native/internal/freeradius"
"git.netcell-it.de/projekte/edgeguard-native/internal/kea"
"git.netcell-it.de/projekte/edgeguard-native/internal/configgen"
"git.netcell-it.de/projekte/edgeguard-native/internal/database"
"git.netcell-it.de/projekte/edgeguard-native/internal/firewall"
"git.netcell-it.de/projekte/edgeguard-native/internal/haproxy"
"git.netcell-it.de/projekte/edgeguard-native/internal/cluster"
"git.netcell-it.de/projekte/edgeguard-native/internal/keepalived"
"git.netcell-it.de/projekte/edgeguard-native/internal/services/configorch"
"git.netcell-it.de/projekte/edgeguard-native/internal/services/secrets"
"git.netcell-it.de/projekte/edgeguard-native/internal/squid"
"git.netcell-it.de/projekte/edgeguard-native/internal/unbound"
"git.netcell-it.de/projekte/edgeguard-native/internal/wireguard"
)
// cmdRenderConfig regenerates every per-service config file from PG
// state. Used after package install (postinst), after admin
// mutations (UI button), or as a manual recovery action.
//
// Flags:
//
// --no-reload Write configs but skip systemctl reload.
// --only=svc1,svc2 Run only the named generators.
func cmdRenderConfig(args []string) int {
skipReload := false
var only []string
for i := 0; i < len(args); i++ {
switch {
case args[i] == "--no-reload":
skipReload = true
case strings.HasPrefix(args[i], "--only="):
val := strings.TrimPrefix(args[i], "--only=")
only = strings.Split(val, ",")
case args[i] == "-h" || args[i] == "--help":
fmt.Println("Usage: edgeguard-ctl render-config [--no-reload] [--only=svc1,svc2]")
return 0
}
}
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
pool, err := database.Open(ctx, database.ConnStringFromEnv())
if err != nil {
fmt.Fprintln(os.Stderr, "render-config: open db:", err)
return 1
}
defer pool.Close()
hap := haproxy.New(pool)
fw := firewall.New(pool)
sq := squid.New(pool)
wg := wireguard.New(pool, secrets.New(""))
ub := unbound.New(pool)
cn := chrony.New(pool)
ke := kea.New(pool)
fr := freeradius.New(pool, secrets.New(""))
if skipReload {
hap.SkipReload = true
fw.SkipReload = true
ke.SkipReload = true
fr.SkipReload = true
}
// keepalived: Node-ID aus node.conf für Prioritäts-Berechnung
var ka configgen.Generator
if lc, err := cluster.LoadLocalConfig(""); err == nil && lc.NodeID != "" {
ka = keepalived.New(pool, lc.NodeID)
}
gens := []configgen.Generator{hap, fw, sq, wg, ub, cn, ke, fr}
if ka != nil {
gens = append(gens, ka)
}
results, runErr := configorch.Run(ctx, gens, only)
fmt.Print(configorch.Summarise(results))
if runErr != nil {
fmt.Fprintln(os.Stderr, "render-config aborted:", runErr)
return 1
}
return 0
}