diff --git a/checker/collect.go b/checker/collect.go index 01b50f4..e444d65 100644 --- a/checker/collect.go +++ b/checker/collect.go @@ -8,6 +8,7 @@ import ( "sort" "strconv" "strings" + "time" sdk "git.happydns.org/checker-sdk-go/checker" tlscontract "git.happydns.org/checker-tls/contract" @@ -191,8 +192,9 @@ func (p *daneProvider) Collect(ctx context.Context, opts sdk.CheckerOptions) (an } data := &DANEData{ - Targets: targets, - Invalid: invalid, + Targets: targets, + Invalid: invalid, + CollectedAt: time.Now().UTC(), } if v, ok := opts[OptionDNSSECValidated]; ok { if b, ok := v.(bool); ok { diff --git a/checker/report.go b/checker/report.go index b909fe3..675388e 100644 --- a/checker/report.go +++ b/checker/report.go @@ -47,6 +47,7 @@ func (p *daneProvider) GetHTMLReport(ctx sdk.ReportContext) (string, error) { } view := reportView{ + CollectedAt: data.CollectedAt.Format("2006-01-02 15:04 MST"), TargetCount: len(data.Targets), Diagnoses: diagnose(data, probes), Rows: rows, @@ -64,6 +65,7 @@ func (p *daneProvider) GetHTMLReport(ctx sdk.ReportContext) (string, error) { // the per-row status label/class and leaf string keeps the template free of // branching beyond simple range/if. type reportView struct { + CollectedAt string TargetCount int Diagnoses []diagnosis Rows []reportRow @@ -164,6 +166,17 @@ func sevRank(s string) int { } } +// hasPKIXUsage reports whether any TLSA record at this target demands PKIX +// validation (usage 0 or 1). +func hasPKIXUsage(t TargetResult) bool { + for _, r := range t.Records { + if r.Usage == UsagePKIXTA || r.Usage == UsagePKIXEE { + return true + } + } + return false +} + // proposedTLSA renders a ready-to-paste replacement RR computed from the // live chain. The (usage, selector, matching) triplet is taken from the // user's first existing record so the suggestion stays consistent with @@ -233,7 +246,7 @@ var reportTemplate = template.Must(template.New("dane").Parse(`

DANE / TLSA

-

{{.TargetCount}} endpoint(s).

+

Collected {{.CollectedAt}} · {{.TargetCount}} endpoint(s).

{{with .Diagnoses}}

Action required

{{range .}}
diff --git a/checker/rule.go b/checker/rule.go index 7586974..c4d63a4 100644 --- a/checker/rule.go +++ b/checker/rule.go @@ -269,17 +269,6 @@ func indexProbes(related []sdk.RelatedObservation) map[string]*tls.TLSProbe { return out } -// hasPKIXUsage reports whether any TLSA record at this target demands PKIX -// validation (usage 0 or 1). -func hasPKIXUsage(t TargetResult) bool { - for _, r := range t.Records { - if r.Usage == UsagePKIXTA || r.Usage == UsagePKIXEE { - return true - } - } - return false -} - func truncHex(s string) string { if len(s) > 12 { return s[:12] + "…" diff --git a/checker/types.go b/checker/types.go index 65e6021..2190b2b 100644 --- a/checker/types.go +++ b/checker/types.go @@ -18,6 +18,8 @@ // SHA-512) are matched against the chain slot implied by the usage. package checker +import "time" + // ObservationKeyDANE is the observation key this checker writes. const ObservationKeyDANE = "dane_checks" @@ -87,7 +89,8 @@ type DANEData struct { // records set the AD bit. Only populated by the standalone interactive // flow (lookupTLSA); nil in managed mode where records come from the // user's zone config and DNSSEC posture is checked elsewhere. - DNSSECValidated *bool `json:"dnssec_validated,omitempty"` + DNSSECValidated *bool `json:"dnssec_validated,omitempty"` + CollectedAt time.Time `json:"collected_at"` } // InvalidRecord describes a TLSA record dropped during Collect.