From 0a41c706aaf43a4a3ec113089c1a28353addd5f1 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Mon, 18 May 2026 10:57:48 +0800 Subject: [PATCH 1/2] Use ctx.States() for alert cards in HTML report Build alert cards from rule states when available; fall back to raw-data analysis (resolve failures, CNAME violations, unreachable targets) when states are absent. --- checker/report.go | 117 ++++++++++++++++++++++++++++------------------ 1 file changed, 72 insertions(+), 45 deletions(-) diff --git a/checker/report.go b/checker/report.go index 8cdb3c2..5d44efb 100644 --- a/checker/report.go +++ b/checker/report.go @@ -256,52 +256,79 @@ func (p *srvProvider) GetHTMLReport(ctx sdk.ReportContext) (string, error) { rd.Records = append(rd.Records, rec) } - if len(resolveFails) > 0 { - rd.Alerts = append(rd.Alerts, reportAlert{ - Severity: "crit", - Title: fmt.Sprintf("DNS resolution failed for %d SRV target(s)", len(resolveFails)), - Body: template.HTML(fmt.Sprintf( - "%s
Clients will not be able to reach the service. Fix: either publish A/AAAA records for the target(s), or remove the broken SRV record.", - strings.Join(resolveFails, "
"))), - }) - } - if len(cnames) > 0 { - rd.Alerts = append(rd.Alerts, reportAlert{ - Severity: "warn", - Title: "SRV target is a CNAME (RFC 2782 violation)", - Body: template.HTML(fmt.Sprintf( - "Target(s): %s
RFC 2782 requires SRV targets to resolve directly to A/AAAA. "+ - "Some clients will refuse to follow the CNAME. Fix: point the SRV record to a hostname with A/AAAA records, "+ - "or replace the CNAME with an ALIAS/ANAME at the DNS provider.", - ""+strings.Join(cnames, ", ")+"")), - }) - } - if len(tcpDown) > 0 { - var items []string - for _, f := range tcpDown { - items = append(items, fmt.Sprintf("%s (%s): %s", - template.HTMLEscapeString(f.address), - template.HTMLEscapeString(f.owner), - template.HTMLEscapeString(f.err))) + // Build alerts from rule states when available; fall back to raw-data + // analysis when the host hasn't threaded rule output through yet. + states := ctx.States() + if len(states) > 0 { + for _, st := range states { + sev := "" + switch st.Status { + case sdk.StatusCrit, sdk.StatusError: + sev = "crit" + case sdk.StatusWarn: + sev = "warn" + case sdk.StatusInfo: + sev = "info" + default: + continue + } + alert := reportAlert{ + Severity: sev, + Title: st.Message, + } + if fix, ok := st.Meta["fix"].(string); ok && fix != "" { + alert.Body = template.HTML(template.HTMLEscapeString(fix)) + } + rd.Alerts = append(rd.Alerts, alert) + } + } else { + if len(resolveFails) > 0 { + rd.Alerts = append(rd.Alerts, reportAlert{ + Severity: "crit", + Title: fmt.Sprintf("DNS resolution failed for %d SRV target(s)", len(resolveFails)), + Body: template.HTML(fmt.Sprintf( + "%s
Clients will not be able to reach the service. Fix: either publish A/AAAA records for the target(s), or remove the broken SRV record.", + strings.Join(resolveFails, "
"))), + }) + } + if len(cnames) > 0 { + rd.Alerts = append(rd.Alerts, reportAlert{ + Severity: "warn", + Title: "SRV target is a CNAME (RFC 2782 violation)", + Body: template.HTML(fmt.Sprintf( + "Target(s): %s
RFC 2782 requires SRV targets to resolve directly to A/AAAA. "+ + "Some clients will refuse to follow the CNAME. Fix: point the SRV record to a hostname with A/AAAA records, "+ + "or replace the CNAME with an ALIAS/ANAME at the DNS provider.", + ""+strings.Join(cnames, ", ")+"")), + }) + } + if len(tcpDown) > 0 { + var items []string + for _, f := range tcpDown { + items = append(items, fmt.Sprintf("%s (%s): %s", + template.HTMLEscapeString(f.address), + template.HTMLEscapeString(f.owner), + template.HTMLEscapeString(f.err))) + } + rd.Alerts = append(rd.Alerts, reportAlert{ + Severity: "crit", + Title: fmt.Sprintf("%d target(s) unreachable on their advertised TCP port", len(tcpDown)), + Body: template.HTML(strings.Join(items, "
") + + "
Check: (1) the server is running and bound to the right port; " + + "(2) firewall/security-group allows inbound TCP to that port; " + + "(3) the SRV record is not pointing at an old IP."), + }) + } + if len(nulls) > 0 && len(nulls) == len(d.Records) { + rd.Alerts = append(rd.Alerts, reportAlert{ + Severity: "warn", + Title: "All SRV records use the null target (\".\"): service is explicitly disabled", + Body: template.HTML( + "RFC 2782 defines a single SRV record with target \".\" to signal that the service is " + + "intentionally not available. If this is what you want, the configuration is correct. " + + "If you expected clients to reach this service, replace the null target with a real hostname."), + }) } - rd.Alerts = append(rd.Alerts, reportAlert{ - Severity: "crit", - Title: fmt.Sprintf("%d target(s) unreachable on their advertised TCP port", len(tcpDown)), - Body: template.HTML(strings.Join(items, "
") + - "
Check: (1) the server is running and bound to the right port; " + - "(2) firewall/security-group allows inbound TCP to that port; " + - "(3) the SRV record is not pointing at an old IP."), - }) - } - if len(nulls) > 0 && len(nulls) == len(d.Records) { - rd.Alerts = append(rd.Alerts, reportAlert{ - Severity: "warn", - Title: "All SRV records use the null target (\".\"): service is explicitly disabled", - Body: template.HTML( - "RFC 2782 defines a single SRV record with target \".\" to signal that the service is " + - "intentionally not available. If this is what you want, the configuration is correct. " + - "If you expected clients to reach this service, replace the null target with a real hostname."), - }) } var buf strings.Builder From b33c8497a217f7d939f75817a077fb7d196064f6 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Mon, 18 May 2026 11:20:50 +0800 Subject: [PATCH 2/2] Bump git.happydns.org/checker-tls to v0.7.0 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6d6ae13..c53916b 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.25.0 require ( git.happydns.org/checker-sdk-go v1.7.0 - git.happydns.org/checker-tls v0.6.2 + git.happydns.org/checker-tls v0.7.0 git.happydns.org/happyDomain v0.7.0 ) diff --git a/go.sum b/go.sum index e41c939..3664c74 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ git.happydns.org/checker-sdk-go v1.7.0 h1:dSgo2js5mfXluLc6x0WWZ0MQULd9XV2GI9z0Usk+Qgw= git.happydns.org/checker-sdk-go v1.7.0/go.mod h1:aNAcfYFfbhvH9kJhE0Njp5GX0dQbxdRB0rJ0KvSC5nI= -git.happydns.org/checker-tls v0.6.2 h1:8oKia1XlD+tklyqrwzmUgFH1Kw8VLSLLF9suZ7Qr14E= -git.happydns.org/checker-tls v0.6.2/go.mod h1:9tpnxg0iOwS+7If64DRG1jqYonUAgxOBuxwfF5mVkL4= +git.happydns.org/checker-tls v0.7.0 h1:mfNHYbHMGS40y+N2rudC2svT/xLK7KCiSa7V8/RhcTM= +git.happydns.org/checker-tls v0.7.0/go.mod h1:wlY4UI3owvqMAtOcXLmskpTpZ7xPjuiV6M42+rFZDQo= git.happydns.org/happyDomain v0.7.0 h1:NV82/NbcSeRm0+IUZqaK3Vu9Ovl5+vv4AigUJZMdwws= git.happydns.org/happyDomain v0.7.0/go.mod h1:5tgkmqFE65kK359rY49V++49wgZ0gco+Gh9X6tbL+bY= github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM=