Check for presence of DS and special CDS 0 0 0 00 removal record

This commit is contained in:
s3lph 2022-04-08 03:33:15 +02:00
parent 6dbc1c3155
commit b175d73156

51
main.go
View file

@ -21,9 +21,17 @@ import (
const namespace = "dnssec"
var removalCds = DsData{
KeyTag: 0,
Algorithm: 0,
DigestType: 0,
Digest: "00",
}
type MetricsCollector struct {
Log log.Logger
signatureOkMetric *prom.GaugeVec
dsPresentMetric *prom.GaugeVec
cdsPresentMetric *prom.GaugeVec
cdsDsMatchMetric *prom.GaugeVec
zones []string
@ -40,6 +48,14 @@ func NewMetricsCollector(zonelist []string, resolver string, logger log.Logger)
},
[]string{"zone", "tld", "parent"},
)
dsPresentMetric := prom.NewGaugeVec(
prom.GaugeOpts{
Namespace: namespace,
Name: "ds_present",
Help: "1 if CDS record is present in the parent zone, 0 otherwise",
},
[]string{"zone", "tld", "parent"},
)
cdsPresentMetric := prom.NewGaugeVec(
prom.GaugeOpts{
Namespace: namespace,
@ -58,6 +74,7 @@ func NewMetricsCollector(zonelist []string, resolver string, logger log.Logger)
)
collector := MetricsCollector{
signatureOkMetric: signatureOkMetric,
dsPresentMetric: dsPresentMetric,
cdsPresentMetric: cdsPresentMetric,
cdsDsMatchMetric: cdsDsMatchMetric,
zones: zonelist,
@ -69,6 +86,7 @@ func NewMetricsCollector(zonelist []string, resolver string, logger log.Logger)
func (c *MetricsCollector) Describe(ch chan<- *prom.Desc) {
c.signatureOkMetric.Describe(ch)
c.dsPresentMetric.Describe(ch)
c.cdsPresentMetric.Describe(ch)
c.cdsDsMatchMetric.Describe(ch)
}
@ -87,7 +105,7 @@ func (c *MetricsCollector) reportMetrics(ch chan<- prom.Metric) error {
if err1 != nil {
continue
}
cdp, cdm, err2 := c.cdsDsMatches(zone)
dsp, cdp, cdm, err2 := c.cdsDsMatches(zone)
if err2 != nil {
continue
}
@ -100,6 +118,7 @@ func (c *MetricsCollector) reportMetrics(ch chan<- prom.Metric) error {
"parent": parent,
}
signatureOkMetric := c.signatureOkMetric.With(promlabels)
dsPresentMetric := c.dsPresentMetric.With(promlabels)
cdsPresentMetric := c.cdsPresentMetric.With(promlabels)
cdsDsMatchMetric := c.cdsDsMatchMetric.With(promlabels)
if sok {
@ -107,6 +126,11 @@ func (c *MetricsCollector) reportMetrics(ch chan<- prom.Metric) error {
} else {
signatureOkMetric.Set(0)
}
if dsp {
dsPresentMetric.Set(1)
} else {
dsPresentMetric.Set(0)
}
if cdp {
cdsPresentMetric.Set(1)
} else {
@ -120,6 +144,7 @@ func (c *MetricsCollector) reportMetrics(ch chan<- prom.Metric) error {
}
}
c.signatureOkMetric.Collect(ch)
c.dsPresentMetric.Collect(ch)
c.cdsPresentMetric.Collect(ch)
c.cdsDsMatchMetric.Collect(ch)
return nil
@ -154,20 +179,20 @@ func (c *MetricsCollector) signatureOk(zone string) (bool, error) {
return false, err
}
level.Debug(c.Log).Log(fmt.Sprintf("SOA header: %+v\n", rsoa.MsgHdr))
return rsoa.MsgHdr.AuthenticatedData, nil
return rsoa.MsgHdr.AuthenticatedData && rsoa.MsgHdr.Rcode == dns.RcodeSuccess, nil
}
func (c *MetricsCollector) cdsDsMatches(zone string) (bool, bool, error) {
func (c *MetricsCollector) cdsDsMatches(zone string) (bool, bool, bool, error) {
dsPresent := false
cdsPresent := false
qcds := new(dns.Msg)
qcds.SetQuestion(dns.Fqdn(zone), dns.TypeCDS)
rcds, _, err := c.DNS.Exchange(qcds, c.Resolver)
if err != nil {
return false, false, err
}
if len(rcds.Answer) == 0 {
// Zone doesn't publish CDS records
return false, false, nil
return dsPresent, cdsPresent, false, err
}
cdsPresent = len(rcds.Answer) > 0
cdsdata := make([]DsData, len(rcds.Answer))
level.Debug(c.Log).Log(fmt.Sprintf("CDS data: %+v\n", rcds.Answer))
for i, a := range rcds.Answer {
@ -185,8 +210,9 @@ func (c *MetricsCollector) cdsDsMatches(zone string) (bool, bool, error) {
qds.SetQuestion(dns.Fqdn(zone), dns.TypeDS)
rds, _, err := c.DNS.Exchange(qds, c.Resolver)
if err != nil {
return true, false, err
return dsPresent, cdsPresent, false, err
}
dsPresent = len(rds.Answer) > 0
dsdata := make([]DsData, len(rds.Answer))
level.Debug(c.Log).Log(fmt.Sprintf("DS data: %+v\n", rds.Answer))
for i, a := range rds.Answer {
@ -200,7 +226,12 @@ func (c *MetricsCollector) cdsDsMatches(zone string) (bool, bool, error) {
}
sort.SliceStable(dsdata, func(a, b int) bool { return dsdata[a].KeyTag < dsdata[b].KeyTag })
return true, Equal(dsdata, cdsdata), nil
match := cdsPresent && Equal(dsdata, cdsdata)
// special case: removal requested
if len(cdsdata) == 1 && len(dsdata) == 0 && cdsdata[0] == removalCds {
match = true
}
return dsPresent, cdsPresent, match, nil
}
func main() {