88 lines
2.6 KiB
Go
88 lines
2.6 KiB
Go
package checker
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sort"
|
|
|
|
sdk "git.happydns.org/checker-sdk-go/checker"
|
|
)
|
|
|
|
// Rules returns the full list of CheckRules exposed by the TLS checker.
|
|
// Each rule covers a single concern (reachability, handshake, chain, hostname,
|
|
// expiry, TLS version, STARTTLS advertisement, cipher suite, …) so the UI can
|
|
// surface a passing-list rather than a single aggregated code.
|
|
func Rules() []sdk.CheckRule {
|
|
return []sdk.CheckRule{
|
|
&endpointsDiscoveredRule{},
|
|
&reachabilityRule{},
|
|
&tlsHandshakeRule{},
|
|
&starttlsAdvertisedRule{},
|
|
&starttlsSupportedRule{},
|
|
&peerCertificateRule{},
|
|
&chainValidityRule{},
|
|
&hostnameMatchRule{},
|
|
&expiryRule{},
|
|
&tlsVersionRule{},
|
|
&cipherSuiteRule{},
|
|
}
|
|
}
|
|
|
|
// loadData fetches the TLS observation. On error, returns a single error
|
|
// state the caller should emit.
|
|
func loadData(ctx context.Context, obs sdk.ObservationGetter) (*TLSData, *sdk.CheckState) {
|
|
var data TLSData
|
|
if err := obs.Get(ctx, ObservationKeyTLSProbes, &data); err != nil {
|
|
return nil, &sdk.CheckState{
|
|
Status: sdk.StatusError,
|
|
Message: fmt.Sprintf("failed to load tls_probes observation: %v", err),
|
|
Code: "tls.observation_error",
|
|
}
|
|
}
|
|
return &data, nil
|
|
}
|
|
|
|
// sortedRefs returns the probe refs in deterministic order. Rules iterate
|
|
// this sorted list so CheckState output is stable.
|
|
func sortedRefs(data *TLSData) []string {
|
|
refs := make([]string, 0, len(data.Probes))
|
|
for ref := range data.Probes {
|
|
refs = append(refs, ref)
|
|
}
|
|
sort.Strings(refs)
|
|
return refs
|
|
}
|
|
|
|
// subjectOf formats the UI-facing subject for a single probe.
|
|
func subjectOf(p TLSProbe) string {
|
|
return fmt.Sprintf("%s://%s", p.Type, p.Endpoint)
|
|
}
|
|
|
|
// metaOf returns a compact meta map to attach to a CheckState.
|
|
func metaOf(p TLSProbe) map[string]any {
|
|
m := map[string]any{
|
|
"type": p.Type,
|
|
"host": p.Host,
|
|
"port": p.Port,
|
|
"sni": p.SNI,
|
|
}
|
|
if p.TLSVersion != "" {
|
|
m["tls_version"] = p.TLSVersion
|
|
}
|
|
return m
|
|
}
|
|
|
|
// passState / infoState / unknownState helpers.
|
|
func passState(code, message string) sdk.CheckState {
|
|
return sdk.CheckState{Status: sdk.StatusOK, Code: code, Message: message}
|
|
}
|
|
func unknownState(code, message string) sdk.CheckState {
|
|
return sdk.CheckState{Status: sdk.StatusUnknown, Code: code, Message: message}
|
|
}
|
|
|
|
// emptyCaseState returns a single state describing "no probes to evaluate".
|
|
// Rules call this when len(data.Probes) == 0 to avoid returning an empty
|
|
// slice (see CheckRule.Evaluate contract).
|
|
func emptyCaseState(code string) sdk.CheckState {
|
|
return unknownState(code, "No TLS endpoints have been discovered for this target yet.")
|
|
}
|