Skip to content

Commit

Permalink
backport of commit d75aee2 (#27903)
Browse files Browse the repository at this point in the history
Co-authored-by: Scott Miller <[email protected]>
  • Loading branch information
1 parent 2b6c8e9 commit 4d49110
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 5 deletions.
9 changes: 7 additions & 2 deletions builtin/credential/cert/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/hashicorp/go-multierror"
lru "github.com/hashicorp/golang-lru/v2"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/locksutil"
"github.com/hashicorp/vault/sdk/helper/ocsp"
"github.com/hashicorp/vault/sdk/logical"
)
Expand All @@ -43,7 +44,8 @@ func Backend() *backend {
// ignoring the error as it only can occur with <= 0 size
cache, _ := lru.New[string, *trusted](defaultRoleCacheSize)
b := backend{
trustedCache: cache,
trustedCache: cache,
trustedCacheLocks: locksutil.CreateLocks(),
}
b.Backend = &framework.Backend{
Help: backendHelp,
Expand Down Expand Up @@ -90,6 +92,8 @@ type backend struct {

trustedCache *lru.Cache[string, *trusted]
trustedCacheDisabled atomic.Bool
trustedCacheLocks []*locksutil.LockEntry
trustedCacheFull atomic.Pointer[trusted]
}

func (b *backend) initialize(ctx context.Context, req *logical.InitializationRequest) error {
Expand Down Expand Up @@ -137,7 +141,7 @@ func (b *backend) updatedConfig(config *config) {
case config.RoleCacheSize < 0:
// Just to clean up memory
b.trustedCacheDisabled.Store(true)
b.trustedCache.Purge()
b.flushTrustedCache()
case config.RoleCacheSize == 0:
config.RoleCacheSize = defaultRoleCacheSize
fallthrough
Expand Down Expand Up @@ -200,6 +204,7 @@ func (b *backend) flushTrustedCache() {
if b.trustedCache != nil { // defensive
b.trustedCache.Purge()
}
b.trustedCacheFull.Store(nil)
}

const backendHelp = `
Expand Down
37 changes: 34 additions & 3 deletions builtin/credential/cert/path_login.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import (
"net/url"
"strings"

"github.com/hashicorp/vault/sdk/helper/locksutil"

"github.com/hashicorp/errwrap"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/vault/sdk/framework"
Expand Down Expand Up @@ -593,15 +595,39 @@ func (b *backend) certificateExtensionsMetadata(clientCert *x509.Certificate, co

func (b *backend) getTrustedCerts(ctx context.Context, storage logical.Storage, certName string) (pool *x509.CertPool, trusted []*ParsedCert, trustedNonCAs []*ParsedCert, conf *ocsp.VerifyConfig) {
if !b.trustedCacheDisabled.Load() {
if trusted, found := b.trustedCache.Get(certName); found {
trusted, found := b.getTrustedCertsFromCache(certName)
if found {
return trusted.pool, trusted.trusted, trusted.trustedNonCAs, trusted.ocspConf
}
}
return b.loadTrustedCerts(ctx, storage, certName)
}

func (b *backend) getTrustedCertsFromCache(certName string) (*trusted, bool) {
if certName == "" {
trusted := b.trustedCacheFull.Load()
if trusted != nil {
return trusted, true
}
} else if trusted, found := b.trustedCache.Get(certName); found {
return trusted, true
}
return nil, false
}

// loadTrustedCerts is used to load all the trusted certificates from the backend
func (b *backend) loadTrustedCerts(ctx context.Context, storage logical.Storage, certName string) (pool *x509.CertPool, trustedCerts []*ParsedCert, trustedNonCAs []*ParsedCert, conf *ocsp.VerifyConfig) {
lock := locksutil.LockForKey(b.trustedCacheLocks, certName)
lock.Lock()
defer lock.Unlock()

if !b.trustedCacheDisabled.Load() {
trusted, found := b.getTrustedCertsFromCache(certName)
if found {
return trusted.pool, trusted.trusted, trusted.trustedNonCAs, trusted.ocspConf
}
}

pool = x509.NewCertPool()
trustedCerts = make([]*ParsedCert, 0)
trustedNonCAs = make([]*ParsedCert, 0)
Expand Down Expand Up @@ -669,12 +695,17 @@ func (b *backend) loadTrustedCerts(ctx context.Context, storage logical.Storage,
}

if !b.trustedCacheDisabled.Load() {
b.trustedCache.Add(certName, &trusted{
entry := &trusted{
pool: pool,
trusted: trustedCerts,
trustedNonCAs: trustedNonCAs,
ocspConf: conf,
})
}
if certName == "" {
b.trustedCacheFull.Store(entry)
} else {
b.trustedCache.Add(certName, entry)
}
}
return
}
Expand Down
5 changes: 5 additions & 0 deletions changelog/27902.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
```release-note:improvement
auth/cert: Cache full list of role trust information separately to avoid
eviction, and avoid duplicate loading during multiple simultaneous logins on
the same role.
```

0 comments on commit 4d49110

Please sign in to comment.