108 lines
3.2 KiB
Go
108 lines
3.2 KiB
Go
package checker
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
sdk "git.happydns.org/checker-sdk-go/checker"
|
|
)
|
|
|
|
// starttlsAdvertisedRule flags STARTTLS endpoints whose server did not
|
|
// advertise the upgrade. Severity depends on RequireSTARTTLS: opportunistic
|
|
// STARTTLS degrades to a warning; mandatory STARTTLS is critical.
|
|
type starttlsAdvertisedRule struct{}
|
|
|
|
func (r *starttlsAdvertisedRule) Name() string { return "tls.starttls_advertised" }
|
|
func (r *starttlsAdvertisedRule) Description() string {
|
|
return "Verifies that STARTTLS endpoints advertise the upgrade capability."
|
|
}
|
|
|
|
func (r *starttlsAdvertisedRule) Evaluate(ctx context.Context, obs sdk.ObservationGetter, _ sdk.CheckerOptions) []sdk.CheckState {
|
|
data, errSt := loadData(ctx, obs)
|
|
if errSt != nil {
|
|
return []sdk.CheckState{*errSt}
|
|
}
|
|
if len(data.Probes) == 0 {
|
|
return []sdk.CheckState{emptyCaseState("tls.starttls_advertised.no_endpoints")}
|
|
}
|
|
|
|
var out []sdk.CheckState
|
|
anySTARTTLS := false
|
|
for _, ref := range sortedRefs(data) {
|
|
p := data.Probes[ref]
|
|
if p.STARTTLSDialect == "" {
|
|
continue
|
|
}
|
|
anySTARTTLS = true
|
|
if !p.STARTTLSNotOffered {
|
|
continue
|
|
}
|
|
status := sdk.StatusWarn
|
|
if p.RequireSTARTTLS {
|
|
status = sdk.StatusCrit
|
|
}
|
|
out = append(out, sdk.CheckState{
|
|
Status: status,
|
|
Code: "tls.starttls_advertised.missing",
|
|
Subject: subjectOf(p),
|
|
Message: fmt.Sprintf("Server on %s does not advertise STARTTLS.", p.Endpoint),
|
|
Meta: metaOf(p),
|
|
})
|
|
}
|
|
if !anySTARTTLS {
|
|
return []sdk.CheckState{unknownState(
|
|
"tls.starttls_advertised.not_applicable",
|
|
"No STARTTLS endpoint in the discovered set.",
|
|
)}
|
|
}
|
|
if len(out) == 0 {
|
|
return []sdk.CheckState{passState(
|
|
"tls.starttls_advertised.ok",
|
|
"STARTTLS is advertised on every STARTTLS endpoint.",
|
|
)}
|
|
}
|
|
return out
|
|
}
|
|
|
|
// starttlsSupportedRule flags endpoints whose STARTTLS dialect is not
|
|
// implemented by this checker. A misconfigured discovery entry (typo, new
|
|
// protocol) should be visible as its own concern rather than blending into
|
|
// generic handshake failures.
|
|
type starttlsSupportedRule struct{}
|
|
|
|
func (r *starttlsSupportedRule) Name() string { return "tls.starttls_dialect_supported" }
|
|
func (r *starttlsSupportedRule) Description() string {
|
|
return "Verifies that discovered STARTTLS dialects are implemented by the checker."
|
|
}
|
|
|
|
func (r *starttlsSupportedRule) Evaluate(ctx context.Context, obs sdk.ObservationGetter, _ sdk.CheckerOptions) []sdk.CheckState {
|
|
data, errSt := loadData(ctx, obs)
|
|
if errSt != nil {
|
|
return []sdk.CheckState{*errSt}
|
|
}
|
|
if len(data.Probes) == 0 {
|
|
return []sdk.CheckState{emptyCaseState("tls.starttls_dialect_supported.no_endpoints")}
|
|
}
|
|
|
|
var out []sdk.CheckState
|
|
for _, ref := range sortedRefs(data) {
|
|
p := data.Probes[ref]
|
|
if !p.STARTTLSUnsupportedProto {
|
|
continue
|
|
}
|
|
out = append(out, sdk.CheckState{
|
|
Status: sdk.StatusError,
|
|
Code: "tls.starttls_dialect_supported.unknown",
|
|
Subject: subjectOf(p),
|
|
Message: fmt.Sprintf("Unsupported STARTTLS dialect %q for %s.", p.STARTTLSDialect, p.Endpoint),
|
|
Meta: metaOf(p),
|
|
})
|
|
}
|
|
if len(out) == 0 {
|
|
return []sdk.CheckState{passState(
|
|
"tls.starttls_dialect_supported.ok",
|
|
"Every STARTTLS dialect encountered is implemented.",
|
|
)}
|
|
}
|
|
return out
|
|
}
|