Initial commit
This commit is contained in:
commit
758c03bdd4
19 changed files with 1429 additions and 0 deletions
92
checker/tls_related.go
Normal file
92
checker/tls_related.go
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
package checker
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
sdk "git.happydns.org/checker-sdk-go/checker"
|
||||
)
|
||||
|
||||
// tlsProbeView is the local, permissive view of a single checker-tls
|
||||
// probe payload. We decode only what the CAA rule needs; unknown fields
|
||||
// are ignored so the TLS checker can evolve its schema independently.
|
||||
//
|
||||
// The IssuerAKI / IssuerDN fields are the cross-checker contract the
|
||||
// CAA rule depends on. They were added to checker-tls so each probe
|
||||
// carries the issuer identity in a form that maps directly to the
|
||||
// CCADB "CAA Identifiers" CSV.
|
||||
type tlsProbeView struct {
|
||||
Host string `json:"host,omitempty"`
|
||||
Port uint16 `json:"port,omitempty"`
|
||||
Endpoint string `json:"endpoint,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Issuer string `json:"issuer,omitempty"`
|
||||
IssuerDN string `json:"issuer_dn,omitempty"`
|
||||
IssuerAKI string `json:"issuer_aki,omitempty"`
|
||||
NotAfter time.Time `json:"not_after,omitempty"`
|
||||
ChainValid *bool `json:"chain_valid,omitempty"`
|
||||
}
|
||||
|
||||
// address returns "host:port" as a human-readable identifier for
|
||||
// Issue.Endpoint when the upstream Endpoint field is missing.
|
||||
func (v *tlsProbeView) address() string {
|
||||
if v.Endpoint != "" {
|
||||
return v.Endpoint
|
||||
}
|
||||
if v.Host != "" && v.Port != 0 {
|
||||
return net.JoinHostPort(v.Host, strconv.FormatUint(uint64(v.Port), 10))
|
||||
}
|
||||
return v.Host
|
||||
}
|
||||
|
||||
// parseTLSRelated decodes a single RelatedObservation into a list of
|
||||
// probes. Two payload shapes are supported to match the dual-shape
|
||||
// contract checker-xmpp already consumes:
|
||||
//
|
||||
// 1. {"probes": {"<ref>": <probe>, …}}: the current checker-tls
|
||||
// format. When r.Ref is set and present in the map, only that
|
||||
// entry is returned; otherwise all probes are returned so a rule
|
||||
// operating at domain scope can still see them.
|
||||
// 2. <probe>: a single top-level probe, kept for back-compat.
|
||||
//
|
||||
// Returns nil when the payload is not a recognizable probe shape.
|
||||
func parseTLSRelated(r sdk.RelatedObservation) []*tlsProbeView {
|
||||
var keyed struct {
|
||||
Probes map[string]tlsProbeView `json:"probes"`
|
||||
}
|
||||
if err := json.Unmarshal(r.Data, &keyed); err == nil && keyed.Probes != nil {
|
||||
if r.Ref != "" {
|
||||
if p, ok := keyed.Probes[r.Ref]; ok {
|
||||
cp := p
|
||||
return []*tlsProbeView{&cp}
|
||||
}
|
||||
}
|
||||
out := make([]*tlsProbeView, 0, len(keyed.Probes))
|
||||
for _, p := range keyed.Probes {
|
||||
cp := p
|
||||
out = append(out, &cp)
|
||||
}
|
||||
return out
|
||||
}
|
||||
var v tlsProbeView
|
||||
if err := json.Unmarshal(r.Data, &v); err != nil {
|
||||
return nil
|
||||
}
|
||||
if v.Host == "" && v.IssuerAKI == "" && v.IssuerDN == "" {
|
||||
return nil
|
||||
}
|
||||
return []*tlsProbeView{&v}
|
||||
}
|
||||
|
||||
// parseAllTLSRelated flattens a slice of RelatedObservations into the
|
||||
// full set of probe views they carry. This is the input the rule works
|
||||
// from; one entry per endpoint, not per observation.
|
||||
func parseAllTLSRelated(related []sdk.RelatedObservation) []*tlsProbeView {
|
||||
var out []*tlsProbeView
|
||||
for _, r := range related {
|
||||
out = append(out, parseTLSRelated(r)...)
|
||||
}
|
||||
return out
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue