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