checker-dav/internal/dav/tls_related_test.go
Pierre-Olivier Mercier 7d5535fddf Initial commit
CalDAV and CardDAV checkers sharing a single Go module. Discovery follows
RFC 6764 (/.well-known + SRV/TXT), authenticated probes cover principal,
home-set, collections and a minimal REPORT query on top of go-webdav.
Common shape in internal/dav/; CalDAV adds a scheduling rule.

Surfaces its context URL (and each secure-SRV target) as TLS endpoints via
the EndpointDiscoverer interface, so the dedicated TLS checker can pick
them up without re-parsing observations.

HTML report foregrounds common misconfigs (well-known returning 200,
missing SRV, plaintext-only SRV, missing DAV capability, skipped auth
phase) as action-item callouts before the full phase breakdown.
2026-04-26 21:47:40 +07:00

82 lines
2.7 KiB
Go

package dav
import (
"encoding/json"
"strings"
"testing"
"time"
sdk "git.happydns.org/checker-sdk-go/checker"
)
func relatedFrom(t *testing.T, payload any) sdk.RelatedObservation {
t.Helper()
b, err := json.Marshal(payload)
if err != nil {
t.Fatalf("marshal: %v", err)
}
return sdk.RelatedObservation{Key: TLSRelatedKey, Data: b}
}
func TestFoldTLSRelated_expiringCertProducesCallout(t *testing.T) {
exp := time.Now().Add(5 * 24 * time.Hour)
related := []sdk.RelatedObservation{relatedFrom(t, map[string]any{
"host": "dav.example.com",
"port": 443,
"not_after": exp,
})}
sums, callouts := foldTLSRelated(related)
if len(sums) != 1 || sums[0].Address != "dav.example.com:443" || sums[0].Status != "warn" {
t.Fatalf("summary: %+v", sums)
}
if len(callouts) != 1 || callouts[0].Severity != "warn" {
t.Fatalf("expected a warn callout, got %+v", callouts)
}
if !strings.Contains(callouts[0].Title, "expires in") {
t.Errorf("callout title: %q", callouts[0].Title)
}
}
func TestFoldTLSRelated_expiredCertCrit(t *testing.T) {
exp := time.Now().Add(-2 * 24 * time.Hour)
_, callouts := foldTLSRelated([]sdk.RelatedObservation{relatedFrom(t, map[string]any{
"host": "dav.example.com", "port": 443, "not_after": exp,
})})
if len(callouts) != 1 || callouts[0].Severity != "crit" {
t.Fatalf("expected crit for expired cert, got %+v", callouts)
}
}
func TestFoldTLSRelated_chainInvalid(t *testing.T) {
_, callouts := foldTLSRelated([]sdk.RelatedObservation{relatedFrom(t, map[string]any{
"host": "dav.example.com", "port": 443, "chain_valid": false,
})})
if len(callouts) != 1 || callouts[0].Severity != "crit" {
t.Fatalf("expected crit for broken chain, got %+v", callouts)
}
}
func TestFoldTLSRelated_explicitIssueWinsOverFlags(t *testing.T) {
_, callouts := foldTLSRelated([]sdk.RelatedObservation{relatedFrom(t, map[string]any{
"host": "dav.example.com", "port": 443,
"chain_valid": false, // would normally synthesize a callout
"issues": []map[string]any{
{"code": "weak_cipher", "severity": "warn", "message": "TLS 1.0 offered", "fix": "disable TLS <1.2"},
},
})})
// When explicit issues exist, we do not also emit synthesized callouts;
// the TLS checker is the source of truth for severity and wording.
if len(callouts) != 1 || callouts[0].Severity != "warn" {
t.Fatalf("want single warn callout, got %+v", callouts)
}
if !strings.Contains(callouts[0].Body, "disable TLS") {
t.Errorf("fix text lost: %q", callouts[0].Body)
}
}
func TestFoldTLSRelated_empty(t *testing.T) {
if sums, callouts := foldTLSRelated(nil); sums != nil || callouts != nil {
t.Errorf("expected nil,nil on nil input, got %+v %+v", sums, callouts)
}
}