110 lines
4.1 KiB
Go
110 lines
4.1 KiB
Go
// This file is part of the happyDomain (R) project.
|
|
// Copyright (c) 2026 happyDomain
|
|
// Authors: Pierre-Olivier Mercier, et al.
|
|
//
|
|
// This program is offered under a commercial and under the AGPL license.
|
|
// For commercial licensing, contact us at <contact@happydomain.org>.
|
|
//
|
|
// For AGPL licensing:
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
package checker
|
|
|
|
import (
|
|
"encoding/json"
|
|
|
|
"github.com/miekg/dns"
|
|
)
|
|
|
|
// ObservationKeyDelegation is the observation key for delegation data.
|
|
const ObservationKeyDelegation = "delegation"
|
|
|
|
// Severity classifies a finding emitted by the delegation checker.
|
|
type Severity string
|
|
|
|
const (
|
|
SeverityInfo Severity = "info"
|
|
SeverityWarn Severity = "warn"
|
|
SeverityCrit Severity = "crit"
|
|
)
|
|
|
|
// DelegationFinding describes a single observation produced while running
|
|
// the delegation testsuite.
|
|
type DelegationFinding struct {
|
|
// Code is a stable machine-readable identifier (e.g. "delegation_ns_mismatch").
|
|
Code string `json:"code"`
|
|
|
|
// Severity grades the finding.
|
|
Severity Severity `json:"severity"`
|
|
|
|
// Message is a human-readable explanation.
|
|
Message string `json:"message"`
|
|
|
|
// Server is the DNS server that exhibited the finding (parent or child),
|
|
// when applicable. Empty for findings tied to the service definition itself.
|
|
Server string `json:"server,omitempty"`
|
|
}
|
|
|
|
// DelegationData is the observation payload stored by the checker. It carries
|
|
// every finding emitted by the testsuite plus the raw observed state from the
|
|
// parent and from each delegated server.
|
|
type DelegationData struct {
|
|
// DelegatedFQDN is the FQDN of the delegated zone (subdomain + parent).
|
|
DelegatedFQDN string `json:"delegated_fqdn"`
|
|
|
|
// ParentZone is the FQDN of the parent zone that delegates DelegatedFQDN.
|
|
ParentZone string `json:"parent_zone"`
|
|
|
|
// ParentNS lists the parent zone's authoritative servers that were
|
|
// queried (FQDNs of NS records).
|
|
ParentNS []string `json:"parent_ns,omitempty"`
|
|
|
|
// AdvertisedNS holds the NS RRset returned by the parent for the
|
|
// delegated FQDN, normalized as lowercase FQDNs.
|
|
AdvertisedNS []string `json:"advertised_ns,omitempty"`
|
|
|
|
// AdvertisedGlue maps an in-bailiwick NS hostname to the glue addresses
|
|
// returned by the parent for that name.
|
|
AdvertisedGlue map[string][]string `json:"advertised_glue,omitempty"`
|
|
|
|
// ParentDS lists the DS records returned by the parent for the
|
|
// delegated FQDN, in their textual presentation form.
|
|
ParentDS []string `json:"parent_ds,omitempty"`
|
|
|
|
// ChildSerials maps an NS hostname to the SOA serial it returns for
|
|
// the delegated FQDN.
|
|
ChildSerials map[string]uint32 `json:"child_serials,omitempty"`
|
|
|
|
// Findings is the list of issues / observations produced by the run.
|
|
Findings []DelegationFinding `json:"findings"`
|
|
}
|
|
|
|
// delegationService is the minimal local mirror of happyDomain's
|
|
// `services/abstract.Delegation` type. It is duplicated on purpose so that
|
|
// this checker does not have to import the (heavy) happyDomain server module
|
|
// just to decode the service payload. github.com/miekg/dns marshals
|
|
// dns.NS / dns.DS to JSON in the same shape happyDomain uses.
|
|
type delegationService struct {
|
|
NameServers []*dns.NS `json:"ns"`
|
|
DS []*dns.DS `json:"ds"`
|
|
}
|
|
|
|
// serviceMessage is the minimal local mirror of happyDomain's ServiceMessage
|
|
// envelope. We only need the embedded service JSON; the rest of the meta
|
|
// fields are ignored.
|
|
type serviceMessage struct {
|
|
Type string `json:"_svctype"`
|
|
Domain string `json:"_domain"`
|
|
Service json.RawMessage `json:"Service"`
|
|
}
|