checker-alias/checker/rules_coexistence.go

58 lines
1.8 KiB
Go

package checker
import (
"context"
"fmt"
sdk "git.happydns.org/checker-sdk-go/checker"
)
type cnameCoexistenceRule struct{}
func (cnameCoexistenceRule) Name() string { return "cname_coexistence" }
func (cnameCoexistenceRule) Description() string {
return "Flags other RRsets that sit at the same owner as a CNAME (RFC 1034 §3.6.2 / RFC 2181 §10.1). Honours allowApexCNAME and recognizeApexFlattening."
}
func (cnameCoexistenceRule) Evaluate(ctx context.Context, obs sdk.ObservationGetter, opts sdk.CheckerOptions) []sdk.CheckState {
data, errState := loadAlias(ctx, obs)
if errState != nil {
return errState
}
if !apexKnown(data) {
return skipped("apex lookup failed")
}
if !data.OwnerHasCNAME {
return skipped("owner has no CNAME")
}
if len(data.Coexisting) == 0 {
return okState(data.Owner, "CNAME is the only RRset at its owner")
}
isApex := data.OwnerIsApex
recognize := recognizeApexFlattening(opts)
allow := allowApexCNAME(opts)
var out []sdk.CheckState
for _, rr := range data.Coexisting {
// Provider-side flattening serves apex A/AAAA on a synthetic owner,
// so the wire-level coexistence is intentional, not a zone bug.
if isApex && recognize && data.ApexFlattening && (rr.Type == "A" || rr.Type == "AAAA") {
continue
}
status := sdk.StatusCrit
if isApex && allow {
status = sdk.StatusWarn
}
out = append(out, withHint(sdk.CheckState{
Status: status,
Subject: data.Owner,
Message: fmt.Sprintf("%s and CNAME both exist at %s (RFC 1034 §3.6.2 / RFC 2181 §10.1)", rr.Type, data.Owner),
Code: rr.Type,
}, "Remove the sibling record or move it under a different label; a name cannot simultaneously carry a CNAME and other data."))
}
if len(out) == 0 {
return okState(data.Owner, "CNAME coexistence exempted by ALIAS/ANAME flattening")
}
return out
}