mirror of
https://github.com/crowdsecurity/crowdsec.git
synced 2025-05-11 12:25:53 +02:00
99 lines
2.2 KiB
Go
99 lines
2.2 KiB
Go
package v1
|
|
|
|
import (
|
|
"crypto/x509"
|
|
"sync"
|
|
"time"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
type cacheEntry struct {
|
|
err error // if nil, the certificate is not revocated
|
|
timestamp time.Time
|
|
}
|
|
|
|
type RevocationCache struct {
|
|
mu sync.RWMutex
|
|
cache map[string]cacheEntry
|
|
expiration time.Duration
|
|
lastPurge time.Time
|
|
logger *log.Entry
|
|
}
|
|
|
|
func NewRevocationCache(expiration time.Duration, logger *log.Entry) *RevocationCache {
|
|
return &RevocationCache{
|
|
cache: make(map[string]cacheEntry),
|
|
expiration: expiration,
|
|
lastPurge: time.Now(),
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
func (*RevocationCache) generateKey(cert *x509.Certificate) string {
|
|
return cert.SerialNumber.String() + "-" + cert.Issuer.String()
|
|
}
|
|
|
|
// purge removes expired entries from the cache
|
|
func (rc *RevocationCache) purgeExpired() {
|
|
// we don't keep a separate interval for the full sweep, we'll just double the expiration
|
|
if time.Since(rc.lastPurge) < rc.expiration {
|
|
return
|
|
}
|
|
|
|
rc.mu.Lock()
|
|
defer rc.mu.Unlock()
|
|
|
|
for key, entry := range rc.cache {
|
|
if time.Since(entry.timestamp) > rc.expiration {
|
|
rc.logger.Debugf("purging expired entry for cert %s", key)
|
|
delete(rc.cache, key)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (rc *RevocationCache) Get(cert *x509.Certificate) (error, bool) { //nolint:revive
|
|
rc.purgeExpired()
|
|
key := rc.generateKey(cert)
|
|
rc.mu.RLock()
|
|
entry, exists := rc.cache[key]
|
|
rc.mu.RUnlock()
|
|
|
|
if !exists {
|
|
rc.logger.Tracef("no cached value for cert %s", key)
|
|
return nil, false
|
|
}
|
|
|
|
// Upgrade to write lock to potentially modify the cache
|
|
rc.mu.Lock()
|
|
defer rc.mu.Unlock()
|
|
|
|
if entry.timestamp.Add(rc.expiration).Before(time.Now()) {
|
|
rc.logger.Debugf("cached value for %s expired, removing from cache", key)
|
|
delete(rc.cache, key)
|
|
|
|
return nil, false
|
|
}
|
|
|
|
rc.logger.Debugf("using cached value for cert %s: %v", key, entry.err)
|
|
|
|
return entry.err, true
|
|
}
|
|
|
|
func (rc *RevocationCache) Set(cert *x509.Certificate, err error) {
|
|
key := rc.generateKey(cert)
|
|
|
|
rc.mu.Lock()
|
|
defer rc.mu.Unlock()
|
|
|
|
rc.cache[key] = cacheEntry{
|
|
err: err,
|
|
timestamp: time.Now(),
|
|
}
|
|
}
|
|
|
|
func (rc *RevocationCache) Empty() {
|
|
rc.mu.Lock()
|
|
defer rc.mu.Unlock()
|
|
rc.cache = make(map[string]cacheEntry)
|
|
}
|