fix(unbound): Apex-Records (@/leer) korrekt zur Zone-FQDN expandieren

Vorher: Renderer hat record.Name 1:1 ins local-data übernommen.
Bei Apex-Records (Operator gibt '@' oder leer ein um die Zone selbst
zu adressieren) kam '@.' raus statt der Zone-FQDN — unbound parsed
das als FQDN '@', was funktional tot ist.

Fix: resolveFQDN(recName, zoneName):
  '@' / leer  → zone + '.'
  endet mit . → as-is
  endet mit zone-suffix → name + '.'
  sonst       → name + '.' + zone + '.'

Renderer baut recordView{DNSRecord, FQDN} pro record.

Test: zone proxy.resdom.loc + record name='@' value='10.10.20.1'
  $ dig @10.10.20.1 +short proxy.resdom.loc
  10.10.20.1

Auch wenn der Operator 'proxy.resdom.loc' als Name eingibt
(absoluter FQDN), 'mailcow' (relativ), oder 'mailcow.proxy.resdom.loc.'
(absolut mit Punkt) — alle drei expandieren korrekt.

Version 1.0.42.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Debian
2026-05-11 07:18:45 +02:00
parent f78ada7732
commit cc500139fc
8 changed files with 36 additions and 10 deletions

View File

@@ -1 +1 @@
1.0.41 1.0.42

View File

@@ -45,7 +45,7 @@ import (
wgsvc "git.netcell-it.de/projekte/edgeguard-native/internal/services/wireguard" wgsvc "git.netcell-it.de/projekte/edgeguard-native/internal/services/wireguard"
) )
var version = "1.0.41" var version = "1.0.42"
func main() { func main() {
addr := os.Getenv("EDGEGUARD_API_ADDR") addr := os.Getenv("EDGEGUARD_API_ADDR")

View File

@@ -9,7 +9,7 @@ import (
"os" "os"
) )
var version = "1.0.41" var version = "1.0.42"
const usage = `edgeguard-ctl — EdgeGuard CLI const usage = `edgeguard-ctl — EdgeGuard CLI

View File

@@ -21,7 +21,7 @@ import (
"git.netcell-it.de/projekte/edgeguard-native/internal/services/tlscerts" "git.netcell-it.de/projekte/edgeguard-native/internal/services/tlscerts"
) )
var version = "1.0.41" var version = "1.0.42"
const ( const (
// renewTickInterval — how often we re-evaluate expiring certs. // renewTickInterval — how often we re-evaluate expiring certs.

View File

@@ -58,7 +58,7 @@ server:
{{range .LocalZones}} {{range .LocalZones}}
local-zone: "{{.Name}}." static local-zone: "{{.Name}}." static
{{- range .Records}} {{- range .Records}}
local-data: "{{.Name}}{{if not (hasSuffix .Name $.dot)}}.{{end}} {{.TTL}} IN {{.RecordType}} {{.Value}}" local-data: "{{.FQDN}} {{.TTL}} IN {{.RecordType}} {{.Value}}"
{{- end}} {{- end}}
{{end}} {{end}}

View File

@@ -50,7 +50,30 @@ type View struct {
type localZoneView struct { type localZoneView struct {
Name string Name string
Records []models.DNSRecord Records []recordView
}
// recordView ist DNSRecord plus FQDN — der Renderer expandiert
// "@"/leer zu zone.Name, relative names zu "<name>.<zone>." Punkt
// am Ende ist für unbound's local-data Pflicht.
type recordView struct {
models.DNSRecord
FQDN string
}
func resolveFQDN(recName, zoneName string) string {
zone := strings.TrimSuffix(zoneName, ".")
n := strings.TrimSpace(recName)
if n == "" || n == "@" {
return zone + "."
}
if strings.HasSuffix(n, ".") {
return n // schon FQDN mit Punkt
}
if strings.HasSuffix(n, "."+zone) || n == zone {
return n + "."
}
return n + "." + zone + "."
} }
type forwardZoneView struct { type forwardZoneView struct {
@@ -96,10 +119,13 @@ func (g *Generator) Render(ctx context.Context) error {
if err != nil { if err != nil {
return fmt.Errorf("records for zone %s: %w", z.Name, err) return fmt.Errorf("records for zone %s: %w", z.Name, err)
} }
active := make([]models.DNSRecord, 0, len(recs)) active := make([]recordView, 0, len(recs))
for _, r := range recs { for _, r := range recs {
if r.Active { if r.Active {
active = append(active, r) active = append(active, recordView{
DNSRecord: r,
FQDN: resolveFQDN(r.Name, z.Name),
})
} }
} }
view.LocalZones = append(view.LocalZones, localZoneView{ view.LocalZones = append(view.LocalZones, localZoneView{

View File

@@ -1,7 +1,7 @@
{ {
"name": "edgeguard-management-ui", "name": "edgeguard-management-ui",
"private": true, "private": true,
"version": "1.0.41", "version": "1.0.42",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

@@ -75,7 +75,7 @@ const NAV: NavSection[] = [
}, },
] ]
const VERSION = '1.0.41' const VERSION = '1.0.42'
export default function Sidebar({ isOpen, onClose }: SidebarProps) { export default function Sidebar({ isOpen, onClose }: SidebarProps) {
const { t } = useTranslation() const { t } = useTranslation()