coredns/plugin/dnssec/cache.go
Miek Gieben 13cef2ee09
plugin/dnssec: use entire RRset as key input (#4537)
* plugin/dnssec: use entire RRset as key input

This uses the entire rrset as input for the hash key; this is to detect
differences in the RRset and generate the correct signature.

As this would then lead to unbounded growth, we periodically (every 8h)
prune the cache of old entries. In theory we could rely on the random
eviction, but it seems nicer to do this in a maintannce loop so that we
remove the unused ones. This required adding a Walk function to the
plugin/pkg/cache.

Signed-off-by: Miek Gieben <miek@miek.nl>

* Update plugin/dnssec/cache.go

Co-authored-by: Chris O'Haver <cohaver@infoblox.com>

Co-authored-by: Chris O'Haver <cohaver@infoblox.com>
2021-04-05 06:45:28 -07:00

48 lines
1.1 KiB
Go

package dnssec
import (
"hash/fnv"
"io"
"time"
"github.com/coredns/coredns/plugin/pkg/cache"
"github.com/miekg/dns"
)
// hash serializes the RRset and returns a signature cache key.
func hash(rrs []dns.RR) uint64 {
h := fnv.New64()
// we need to hash the entire RRset to pick the correct sig, if the rrset
// changes for whatever reason we should resign.
// We could use wirefmt, or the string format, both create garbage when creating
// the hash key. And of course is a uint64 big enough?
for _, rr := range rrs {
io.WriteString(h, rr.String())
}
return h.Sum64()
}
func periodicClean(c *cache.Cache, stop <-chan struct{}) {
tick := time.NewTicker(8 * time.Hour)
defer tick.Stop()
for {
select {
case <-tick.C:
// we sign for 8 days, check if a signature in the cache reached 75% of that (i.e. 6), if found delete
// the signature
is75 := time.Now().UTC().Add(sixDays)
c.Walk(func(items map[uint64]interface{}, key uint64) bool {
sig := items[key].(*dns.RRSIG)
if !sig.ValidityPeriod(is75) {
delete(items, key)
}
return true
})
case <-stop:
return
}
}
}