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.")} }