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>
44 lines
2.0 KiB
Go
44 lines
2.0 KiB
Go
package models
|
|
|
|
import "time"
|
|
|
|
// RADIUSSettings ist die node-lokale Singleton-Konfiguration des
|
|
// FreeRADIUS-Servers (ob diese Node RADIUS betreibt + Listen-Adressen).
|
|
type RADIUSSettings struct {
|
|
ID int `gorm:"column:id;primaryKey" json:"id"`
|
|
Enabled bool `gorm:"column:enabled" json:"enabled"`
|
|
ListenAddresses string `gorm:"column:listen_addresses" json:"listen_addresses"`
|
|
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
|
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
|
}
|
|
|
|
func (RADIUSSettings) TableName() string { return "radius_settings" }
|
|
|
|
// RADIUSClient ist ein NAS-Client (IP/CIDR + Shared Secret). SecretEnc
|
|
// wird via secrets.Box verschlüsselt und nie serialisiert.
|
|
type RADIUSClient struct {
|
|
ID int64 `gorm:"column:id;primaryKey" json:"id"`
|
|
Name string `gorm:"column:name" json:"name"`
|
|
IPAddr string `gorm:"column:ipaddr" json:"ipaddr"`
|
|
SecretEnc []byte `gorm:"column:secret_enc" json:"-"`
|
|
Active bool `gorm:"column:active" json:"active"`
|
|
Description string `gorm:"column:description" json:"description"`
|
|
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
|
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
|
}
|
|
|
|
func (RADIUSClient) TableName() string { return "radius_clients" }
|
|
|
|
// RADIUSUser ist ein PAP/CHAP-Benutzer. PasswordEnc wird via secrets.Box
|
|
// verschlüsselt und nie serialisiert.
|
|
type RADIUSUser struct {
|
|
ID int64 `gorm:"column:id;primaryKey" json:"id"`
|
|
Username string `gorm:"column:username" json:"username"`
|
|
PasswordEnc []byte `gorm:"column:password_enc" json:"-"`
|
|
Active bool `gorm:"column:active" json:"active"`
|
|
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
|
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
|
}
|
|
|
|
func (RADIUSUser) TableName() string { return "radius_users" }
|