checker-alias/checker/rules_apex.go

93 lines
3 KiB
Go

package checker
import (
"context"
"fmt"
sdk "git.happydns.org/checker-sdk-go/checker"
)
type apexLookupRule struct{}
func (apexLookupRule) Name() string { return "apex_lookup" }
func (apexLookupRule) Description() string {
return "Verifies the zone apex (SOA) of the checked name can be located."
}
func (apexLookupRule) Evaluate(ctx context.Context, obs sdk.ObservationGetter, _ sdk.CheckerOptions) []sdk.CheckState {
data, errState := loadAlias(ctx, obs)
if errState != nil {
return errState
}
if data.Apex != "" {
return okState(data.Apex, fmt.Sprintf("apex %s located", data.Apex))
}
return []sdk.CheckState{withHint(sdk.CheckState{
Status: sdk.StatusCrit,
Subject: data.Owner,
Message: fmt.Sprintf("could not locate zone apex: %s", data.ApexLookupError),
}, "Check that the parent delegation exists and that the zone is published.")}
}
type cnameAtApexRule struct{}
func (cnameAtApexRule) Name() string { return "cname_at_apex" }
func (cnameAtApexRule) Description() string {
return "Flags a CNAME at the zone apex, which conflicts with the SOA/NS records the apex must carry (RFC 1912 §2.4). Honours the shared allowApexCNAME option."
}
func (cnameAtApexRule) 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.OwnerIsApex {
return skipped("owner is not the zone apex")
}
if !data.ApexHasCNAME {
return okState(data.Apex, "no CNAME at apex")
}
status := sdk.StatusCrit
if allowApexCNAME(opts) {
status = sdk.StatusWarn
}
return []sdk.CheckState{withHint(sdk.CheckState{
Status: status,
Subject: data.Apex,
Message: fmt.Sprintf("CNAME at apex %s conflicts with SOA/NS (RFC 1912 §2.4)", data.Apex),
}, "Use the provider's ALIAS/ANAME flattening, an HTTP redirect, or move content to a sub-label such as www.")}
}
type apexFlatteningRule struct{}
func (apexFlatteningRule) Name() string { return "apex_flattening" }
func (apexFlatteningRule) Description() string {
return "Notes ALIAS/ANAME provider-side flattening (A/AAAA served at apex alongside SOA/NS)."
}
func (apexFlatteningRule) 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.OwnerIsApex {
return skipped("owner is not the zone apex")
}
if !data.ApexFlattening {
return okState(data.Apex, "no ALIAS/ANAME flattening detected")
}
if !recognizeApexFlattening(opts) {
return skipped("recognizeApexFlattening disabled")
}
return []sdk.CheckState{withHint(sdk.CheckState{
Status: sdk.StatusInfo,
Subject: data.Apex,
Message: fmt.Sprintf("apex %s serves A/AAAA directly (provider-side ALIAS/ANAME flattening)", data.Apex),
}, "Keep the upstream target's TTL in mind: apex A/AAAA will only update as fast as the provider re-flattens.")}
}