checker: resolve relative NS labels using the zone origin
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/tag Build is failing

NS hostnames stored in happyDomain's abstract.Origin service are encoded
relative to the zone apex (e.g. "ns0" instead of "ns0.example.com.").
normalizeNSList was calling dns.Fqdn() directly, turning "ns0" into the
useless single-label "ns0." rather than the correct FQDN.

Expose domain_name in ServiceOpts so happyDomain auto-fills the zone
apex at service scope, then use sdk.JoinRelative in normalizeNSList to
absolutize relative labels.  Absolute FQDNs (trailing dot) are kept
as-is so external nameservers round-trip safely.
This commit is contained in:
nemunaire 2026-05-16 21:32:09 +08:00
commit 744a75b25d
3 changed files with 17 additions and 6 deletions

View file

@ -32,7 +32,7 @@ func (p *authoritativeConsistencyProvider) Collect(ctx context.Context, opts sdk
data := &ObservationData{ data := &ObservationData{
Zone: dns.Fqdn(zone), Zone: dns.Fqdn(zone),
HasSOA: svc.SOA != nil, HasSOA: svc.SOA != nil,
DeclaredNS: normalizeNSList(svc.NameServers), DeclaredNS: normalizeNSList(svc.NameServers, zone),
Results: map[string]*NSResult{}, Results: map[string]*NSResult{},
} }
if svc.SOA != nil { if svc.SOA != nil {
@ -167,13 +167,17 @@ func loadZone(opts sdk.CheckerOptions, svc *originService) (string, error) {
return "", fmt.Errorf("no zone name provided (missing 'domain_name' option and SOA header)") return "", fmt.Errorf("no zone name provided (missing 'domain_name' option and SOA header)")
} }
func normalizeNSList(ns []*dns.NS) []string { func normalizeNSList(ns []*dns.NS, origin string) []string {
out := make([]string, 0, len(ns)) out := make([]string, 0, len(ns))
for _, n := range ns { for _, n := range ns {
if n == nil { if n == nil {
continue continue
} }
out = append(out, strings.ToLower(dns.Fqdn(n.Ns))) name := n.Ns
if !strings.HasSuffix(name, ".") {
name = sdk.JoinRelative(name, strings.TrimSuffix(origin, "."))
}
out = append(out, strings.ToLower(dns.Fqdn(name)))
} }
sort.Strings(out) sort.Strings(out)
return out return out

View file

@ -80,13 +80,15 @@ func TestDiffStringSets_Equal(t *testing.T) {
} }
func TestNormalizeNSList(t *testing.T) { func TestNormalizeNSList(t *testing.T) {
// Relative labels (no trailing dot) are joined with the zone origin.
// Absolute FQDNs (trailing dot) are kept as-is.
in := []*dns.NS{ in := []*dns.NS{
{Ns: "NS2.Example.COM"}, {Ns: "ns2"},
nil, nil,
{Ns: "ns1.example.com."}, {Ns: "ns1.example.com."},
{Ns: "NS1.example.com"}, {Ns: "ns1"},
} }
got := normalizeNSList(in) got := normalizeNSList(in, "example.com.")
want := []string{"ns1.example.com.", "ns1.example.com.", "ns2.example.com."} want := []string{"ns1.example.com.", "ns1.example.com.", "ns2.example.com."}
if !reflect.DeepEqual(got, want) { if !reflect.DeepEqual(got, want) {
t.Errorf("got %v, want %v", got, want) t.Errorf("got %v, want %v", got, want)

View file

@ -110,6 +110,11 @@ func (p *authoritativeConsistencyProvider) Definition() *sdk.CheckerDefinition {
Label: "Origin service", Label: "Origin service",
AutoFill: sdk.AutoFillService, AutoFill: sdk.AutoFillService,
}, },
{
Id: "domain_name",
Label: "Zone name",
AutoFill: sdk.AutoFillDomainName,
},
}, },
}, },
Rules: Rules(), Rules: Rules(),