From b175d73156b88271dfe330711d3a4ae08c6e3e5a Mon Sep 17 00:00:00 2001 From: s3lph <1375407-s3lph@users.noreply.gitlab.com> Date: Fri, 8 Apr 2022 03:33:15 +0200 Subject: [PATCH] Check for presence of DS and special CDS 0 0 0 00 removal record --- main.go | 51 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/main.go b/main.go index 66e442e..3a9a0e2 100644 --- a/main.go +++ b/main.go @@ -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() {