Initial commit
This commit is contained in:
commit
63d5846f00
33 changed files with 5407 additions and 0 deletions
200
checker/tls_related_test.go
Normal file
200
checker/tls_related_test.go
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
package checker
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
sdk "git.happydns.org/checker-sdk-go/checker"
|
||||
)
|
||||
|
||||
func mustJSON(t *testing.T, v any) json.RawMessage {
|
||||
t.Helper()
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal: %v", err)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func TestTLSProbeView_AddressEndpointWins(t *testing.T) {
|
||||
v := tlsProbeView{Endpoint: "mx.example.com:25", Host: "ignored", Port: 999}
|
||||
if got := v.address(); got != "mx.example.com:25" {
|
||||
t.Errorf("got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSProbeView_AddressFromHostPort(t *testing.T) {
|
||||
v := tlsProbeView{Host: "mx.example.com", Port: 25}
|
||||
if got := v.address(); got != "mx.example.com:25" {
|
||||
t.Errorf("got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSProbeView_AddressEmpty(t *testing.T) {
|
||||
v := tlsProbeView{}
|
||||
if got := v.address(); got != "" {
|
||||
t.Errorf("expected empty, got %q", got)
|
||||
}
|
||||
v2 := tlsProbeView{Host: "only-host"}
|
||||
if got := v2.address(); got != "" {
|
||||
t.Errorf("host without port should be empty, got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseTLSRelated_KeyedByRef(t *testing.T) {
|
||||
payload := map[string]any{
|
||||
"probes": map[string]any{
|
||||
"ref-A": map[string]any{"host": "mx.example.com", "port": 25, "tls_version": "TLS1.3"},
|
||||
},
|
||||
}
|
||||
r := sdk.RelatedObservation{Ref: "ref-A", Data: mustJSON(t, payload)}
|
||||
v := parseTLSRelated(r)
|
||||
if v == nil {
|
||||
t.Fatal("expected match")
|
||||
}
|
||||
if v.TLSVersion != "TLS1.3" {
|
||||
t.Errorf("got %q", v.TLSVersion)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseTLSRelated_KeyedRefMissing(t *testing.T) {
|
||||
payload := map[string]any{
|
||||
"probes": map[string]any{
|
||||
"some-other-ref": map[string]any{"host": "mx", "port": 25},
|
||||
},
|
||||
}
|
||||
r := sdk.RelatedObservation{Ref: "ref-A", Data: mustJSON(t, payload)}
|
||||
if got := parseTLSRelated(r); got != nil {
|
||||
t.Errorf("expected nil for missing ref, got %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseTLSRelated_FlatTopLevel(t *testing.T) {
|
||||
payload := map[string]any{"host": "mx.example.com", "port": 25}
|
||||
r := sdk.RelatedObservation{Data: mustJSON(t, payload)}
|
||||
v := parseTLSRelated(r)
|
||||
if v == nil || v.Host != "mx.example.com" {
|
||||
t.Errorf("got %+v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseTLSRelated_BadJSON(t *testing.T) {
|
||||
r := sdk.RelatedObservation{Data: json.RawMessage("not json at all")}
|
||||
if got := parseTLSRelated(r); got != nil {
|
||||
t.Errorf("expected nil for bad json, got %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSIssuesFromRelated_FromIssuesList(t *testing.T) {
|
||||
payload := map[string]any{
|
||||
"host": "mx.example.com", "port": 25,
|
||||
"issues": []map[string]any{
|
||||
{"code": "cert.expired", "severity": "crit", "message": "expired", "fix": "renew"},
|
||||
{"code": "cert.weakcipher", "severity": "WARN", "message": "weak"},
|
||||
{"code": "ignore-me", "severity": "bogus"}, // unknown severity → skipped
|
||||
},
|
||||
}
|
||||
related := []sdk.RelatedObservation{{Data: mustJSON(t, payload)}}
|
||||
issues := tlsIssuesFromRelated(related)
|
||||
if len(issues) != 2 {
|
||||
t.Fatalf("want 2 issues, got %d (%+v)", len(issues), issues)
|
||||
}
|
||||
if issues[0].Code != "smtp.tls.cert.expired" || issues[0].Severity != SeverityCrit {
|
||||
t.Errorf("first: %+v", issues[0])
|
||||
}
|
||||
if issues[1].Severity != SeverityWarn {
|
||||
t.Errorf("second severity: %q", issues[1].Severity)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSIssuesFromRelated_EmptyCode(t *testing.T) {
|
||||
payload := map[string]any{
|
||||
"host": "mx", "port": 25,
|
||||
"issues": []map[string]any{{"severity": "warn", "message": "x"}},
|
||||
}
|
||||
related := []sdk.RelatedObservation{{Data: mustJSON(t, payload)}}
|
||||
issues := tlsIssuesFromRelated(related)
|
||||
if len(issues) != 1 || issues[0].Code != "smtp.tls.tls.unknown" {
|
||||
t.Errorf("expected fallback code, got %+v", issues)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSIssuesFromRelated_FromShorthand_ChainInvalid(t *testing.T) {
|
||||
chainBad := false
|
||||
payload := map[string]any{
|
||||
"host": "mx", "port": 25, "chain_valid": chainBad,
|
||||
}
|
||||
related := []sdk.RelatedObservation{{Data: mustJSON(t, payload)}}
|
||||
issues := tlsIssuesFromRelated(related)
|
||||
if len(issues) != 1 || issues[0].Severity != SeverityCrit {
|
||||
t.Errorf("expected single crit issue, got %+v", issues)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSIssuesFromRelated_HostnameMismatch(t *testing.T) {
|
||||
hn := false
|
||||
payload := map[string]any{"host": "mx", "port": 25, "hostname_match": hn}
|
||||
related := []sdk.RelatedObservation{{Data: mustJSON(t, payload)}}
|
||||
issues := tlsIssuesFromRelated(related)
|
||||
if len(issues) != 1 || issues[0].Severity != SeverityCrit {
|
||||
t.Errorf("expected hostname-mismatch crit, got %+v", issues)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSIssuesFromRelated_ExpiringSoon(t *testing.T) {
|
||||
soon := time.Now().Add(48 * time.Hour)
|
||||
payload := map[string]any{"host": "mx", "port": 25, "not_after": soon}
|
||||
issues := tlsIssuesFromRelated([]sdk.RelatedObservation{{Data: mustJSON(t, payload)}})
|
||||
if len(issues) != 1 || issues[0].Severity != SeverityWarn {
|
||||
t.Errorf("expected warn, got %+v", issues)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSIssuesFromRelated_Expired(t *testing.T) {
|
||||
past := time.Now().Add(-1 * time.Hour)
|
||||
payload := map[string]any{"host": "mx", "port": 25, "not_after": past}
|
||||
issues := tlsIssuesFromRelated([]sdk.RelatedObservation{{Data: mustJSON(t, payload)}})
|
||||
if len(issues) != 1 || issues[0].Severity != SeverityCrit {
|
||||
t.Errorf("expected crit (expired), got %+v", issues)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSIssuesFromRelated_NoSeverityNoIssue(t *testing.T) {
|
||||
yes := true
|
||||
notAfter := time.Now().Add(365 * 24 * time.Hour)
|
||||
payload := map[string]any{
|
||||
"host": "mx", "port": 25,
|
||||
"chain_valid": yes, "hostname_match": yes, "not_after": notAfter,
|
||||
}
|
||||
if got := tlsIssuesFromRelated([]sdk.RelatedObservation{{Data: mustJSON(t, payload)}}); len(got) != 0 {
|
||||
t.Errorf("happy path: expected no issues, got %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWorstSeverity_Ordering(t *testing.T) {
|
||||
v := tlsProbeView{
|
||||
Issues: []struct {
|
||||
Code string `json:"code"`
|
||||
Severity string `json:"severity"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Fix string `json:"fix,omitempty"`
|
||||
}{
|
||||
{Code: "a", Severity: "info"},
|
||||
{Code: "b", Severity: "warn"},
|
||||
},
|
||||
}
|
||||
if got := v.worstSeverity(); got != SeverityWarn {
|
||||
t.Errorf("info+warn → warn, got %q", got)
|
||||
}
|
||||
|
||||
v.Issues = append(v.Issues, struct {
|
||||
Code string `json:"code"`
|
||||
Severity string `json:"severity"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Fix string `json:"fix,omitempty"`
|
||||
}{Code: "c", Severity: "CRIT"})
|
||||
if got := v.worstSeverity(); got != SeverityCrit {
|
||||
t.Errorf("with crit → crit, got %q", got)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue