Initial commit
This commit is contained in:
commit
66cf1fc9aa
30 changed files with 2735 additions and 0 deletions
110
checker/rule.go
Normal file
110
checker/rule.go
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
package checker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
sdk "git.happydns.org/checker-sdk-go/checker"
|
||||
)
|
||||
|
||||
// Rules returns the rule set surfaced to happyDomain. After the
|
||||
// registry refactor we expose a single, generic rule that emits one
|
||||
// CheckState per source result: the per-source verdict lives in
|
||||
// CheckState.Subject (the source name) and CheckState.Code carries the
|
||||
// canonical hit / clean / disabled / error flavour.
|
||||
func Rules() []sdk.CheckRule {
|
||||
return []sdk.CheckRule{&sourceRule{}}
|
||||
}
|
||||
|
||||
type sourceRule struct{}
|
||||
|
||||
func (*sourceRule) Name() string { return "source_listed" }
|
||||
func (*sourceRule) Description() string {
|
||||
return "Emits one state per reputation source: Critical/Warning when the source flags the domain, OK when clean, Info when the source is disabled, and Warning on transient query errors."
|
||||
}
|
||||
|
||||
func (*sourceRule) Evaluate(ctx context.Context, obs sdk.ObservationGetter, opts sdk.CheckerOptions) []sdk.CheckState {
|
||||
var data BlacklistData
|
||||
if err := obs.Get(ctx, ObservationKeyBlacklist, &data); err != nil {
|
||||
return []sdk.CheckState{{
|
||||
Status: sdk.StatusError,
|
||||
Message: fmt.Sprintf("failed to get observation: %v", err),
|
||||
Code: "blacklist_obs_error",
|
||||
}}
|
||||
}
|
||||
|
||||
if len(data.Results) == 0 {
|
||||
return []sdk.CheckState{{
|
||||
Status: sdk.StatusInfo, Message: "No reputation sources registered.",
|
||||
Code: "blacklist_no_sources",
|
||||
}}
|
||||
}
|
||||
|
||||
out := make([]sdk.CheckState, 0, len(data.Results))
|
||||
for _, r := range data.Results {
|
||||
out = append(out, evaluateOne(r))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func evaluateOne(r SourceResult) sdk.CheckState {
|
||||
subj := r.SourceName
|
||||
if r.Subject != "" && r.Subject != r.SourceName {
|
||||
subj = r.SourceName + " / " + r.Subject
|
||||
}
|
||||
switch {
|
||||
case !r.Enabled:
|
||||
return sdk.CheckState{
|
||||
Status: sdk.StatusUnknown, Subject: subj,
|
||||
Message: subj + ": disabled or not configured.",
|
||||
Code: "source_disabled",
|
||||
}
|
||||
case r.BlockedQuery:
|
||||
return sdk.CheckState{
|
||||
Status: sdk.StatusError,
|
||||
Subject: subj,
|
||||
Message: fmt.Sprintf("%s: resolver is blocked, result unreliable: %s", subj, joinNonEmpty(r.Reasons, "; ")),
|
||||
Code: "source_resolver_blocked",
|
||||
}
|
||||
case r.Error != "":
|
||||
return sdk.CheckState{
|
||||
Status: sdk.StatusWarn, Subject: subj,
|
||||
Message: subj + ": query failed: " + r.Error,
|
||||
Code: "source_error",
|
||||
}
|
||||
case r.Listed:
|
||||
return sdk.CheckState{
|
||||
Status: severityToStatus(r.Severity),
|
||||
Subject: subj,
|
||||
Message: fmt.Sprintf("Listed in %s: %s", subj, joinNonEmpty(r.Reasons, "; ")),
|
||||
Code: "source_listed",
|
||||
Meta: map[string]any{
|
||||
"source_id": r.SourceID,
|
||||
"reasons": r.Reasons,
|
||||
"lookup_url": r.LookupURL,
|
||||
"removal_url": r.RemovalURL,
|
||||
"reference": r.Reference,
|
||||
},
|
||||
}
|
||||
default:
|
||||
return sdk.CheckState{
|
||||
Status: sdk.StatusOK, Subject: subj,
|
||||
Message: subj + ": clean.",
|
||||
Code: "source_clean",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func severityToStatus(sev string) sdk.Status {
|
||||
switch sev {
|
||||
case SeverityCrit:
|
||||
return sdk.StatusCrit
|
||||
case SeverityWarn:
|
||||
return sdk.StatusWarn
|
||||
case SeverityInfo:
|
||||
return sdk.StatusInfo
|
||||
case SeverityOK:
|
||||
return sdk.StatusOK
|
||||
}
|
||||
return sdk.StatusCrit
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue