Initial commit
This commit is contained in:
commit
848df76c3b
16 changed files with 939 additions and 0 deletions
134
checker/rule.go
Normal file
134
checker/rule.go
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
// This file is part of the happyDomain (R) project.
|
||||
// Copyright (c) 2020-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 (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
sdk "git.happydns.org/checker-sdk-go/checker"
|
||||
)
|
||||
|
||||
// failLevels associates each check name with the severity it raises when it
|
||||
// fails. Names must match those produced by checkServerAddr.
|
||||
var failLevels = map[string]int{
|
||||
"AXFR refused": statusCrit,
|
||||
"IXFR refused": statusWarn,
|
||||
"No recursion": statusWarn,
|
||||
"ANY handled (RFC 8482)": statusWarn,
|
||||
"Is authoritative": statusInfo,
|
||||
}
|
||||
|
||||
// Rule returns a new NS restrictions evaluation rule.
|
||||
func Rule() sdk.CheckRule {
|
||||
return &nsRule{}
|
||||
}
|
||||
|
||||
type nsRule struct{}
|
||||
|
||||
func (r *nsRule) Name() string { return "ns_restrictions_check" }
|
||||
|
||||
func (r *nsRule) Description() string {
|
||||
return "Checks nameservers for AXFR/IXFR acceptance, recursion availability, RFC 8482 ANY handling and authoritative status"
|
||||
}
|
||||
|
||||
func (r *nsRule) Evaluate(ctx context.Context, obs sdk.ObservationGetter, opts sdk.CheckerOptions) sdk.CheckState {
|
||||
var report NSRestrictionsReport
|
||||
if err := obs.Get(ctx, ObservationKeyNSRestrictions, &report); err != nil {
|
||||
return sdk.CheckState{
|
||||
Status: sdk.StatusError,
|
||||
Message: fmt.Sprintf("Failed to get NS restrictions data: %v", err),
|
||||
Code: "ns_restrictions_error",
|
||||
}
|
||||
}
|
||||
|
||||
overall := statusOK
|
||||
var summaryParts []string
|
||||
|
||||
for _, srv := range report.Servers {
|
||||
serverWorst := statusOK
|
||||
for _, item := range srv.Checks {
|
||||
if item.OK {
|
||||
continue
|
||||
}
|
||||
level, ok := failLevels[item.Name]
|
||||
if !ok {
|
||||
// Unknown check (e.g. "DNS resolution", "IPv6 connectivity")
|
||||
// — treat a failure as a warning by default.
|
||||
level = statusWarn
|
||||
}
|
||||
if level > serverWorst {
|
||||
serverWorst = level
|
||||
}
|
||||
}
|
||||
|
||||
if serverWorst > overall {
|
||||
overall = serverWorst
|
||||
}
|
||||
|
||||
label := srv.Name
|
||||
if srv.Address != "" {
|
||||
label = fmt.Sprintf("%s (%s)", srv.Name, srv.Address)
|
||||
}
|
||||
summaryParts = append(summaryParts, fmt.Sprintf("%s: %s", label, statusName(serverWorst)))
|
||||
}
|
||||
|
||||
return sdk.CheckState{
|
||||
Status: toSDKStatus(overall),
|
||||
Message: strings.Join(summaryParts, " | "),
|
||||
Code: "ns_restrictions_result",
|
||||
Meta: map[string]any{
|
||||
"servers": report.Servers,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func statusName(s int) string {
|
||||
switch s {
|
||||
case statusOK:
|
||||
return "OK"
|
||||
case statusInfo:
|
||||
return "INFO"
|
||||
case statusWarn:
|
||||
return "WARN"
|
||||
case statusCrit:
|
||||
return "CRITICAL"
|
||||
default:
|
||||
return "UNKNOWN"
|
||||
}
|
||||
}
|
||||
|
||||
func toSDKStatus(s int) sdk.Status {
|
||||
switch s {
|
||||
case statusOK:
|
||||
return sdk.StatusOK
|
||||
case statusInfo:
|
||||
return sdk.StatusInfo
|
||||
case statusWarn:
|
||||
return sdk.StatusWarn
|
||||
case statusCrit:
|
||||
return sdk.StatusCrit
|
||||
default:
|
||||
return sdk.StatusUnknown
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue