mirror of
https://github.com/hashicorp/vault.git
synced 2025-11-12 22:31:39 +01:00
transit cache is an Interface implemented by wrapped versions of sync… (#6225)
* transit cache is an Interface implemented by wrapped versions of syncmap and golang-lru * transit cache is an Interface implemented by wrapped versions of syncmap and golang-lru * changed some import paths to point to sdk * Apply suggestions from code review Co-Authored-By: Lexman42 <Lexman42@users.noreply.github.com> * updates docs with information on transit/cache-config endpoint * updates vendored files * fixes policy tests to actually use a cache where expected and renames the struct and storage path used for cache configurations to be more generic * updates document links * fixed a typo in a documentation link * changes cache_size to just size for the cache-config endpoint
This commit is contained in:
parent
4d0d70551d
commit
4ed616dacb
@ -4,20 +4,25 @@ import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/vault/sdk/framework"
|
||||
"github.com/hashicorp/vault/sdk/helper/keysutil"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
)
|
||||
|
||||
func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) {
|
||||
b := Backend(conf)
|
||||
|
||||
b, err := Backend(ctx, conf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := b.Setup(ctx, conf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func Backend(conf *logical.BackendConfig) *backend {
|
||||
func Backend(ctx context.Context, conf *logical.BackendConfig) (*backend, error) {
|
||||
var b backend
|
||||
b.Backend = &framework.Backend{
|
||||
PathsSpecial: &logical.Paths{
|
||||
@ -47,6 +52,7 @@ func Backend(conf *logical.BackendConfig) *backend {
|
||||
b.pathBackup(),
|
||||
b.pathRestore(),
|
||||
b.pathTrim(),
|
||||
b.pathCacheConfig(),
|
||||
},
|
||||
|
||||
Secrets: []*framework.Secret{},
|
||||
@ -54,9 +60,24 @@ func Backend(conf *logical.BackendConfig) *backend {
|
||||
BackendType: logical.TypeLogical,
|
||||
}
|
||||
|
||||
b.lm = keysutil.NewLockManager(conf.System.CachingDisabled())
|
||||
// determine cacheSize to use. Defaults to 0 which means unlimited
|
||||
cacheSize := 0
|
||||
useCache := !conf.System.CachingDisabled()
|
||||
if useCache {
|
||||
var err error
|
||||
cacheSize, err = GetCacheSizeFromStorage(ctx, conf.StorageView)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("Error retrieving cache size from storage: {{err}}", err)
|
||||
}
|
||||
}
|
||||
|
||||
return &b
|
||||
var err error
|
||||
b.lm, err = keysutil.NewLockManager(useCache, cacheSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &b, nil
|
||||
}
|
||||
|
||||
type backend struct {
|
||||
@ -64,6 +85,22 @@ type backend struct {
|
||||
lm *keysutil.LockManager
|
||||
}
|
||||
|
||||
func GetCacheSizeFromStorage(ctx context.Context, s logical.Storage) (int, error) {
|
||||
size := 0
|
||||
entry, err := s.Get(ctx, "config/cache")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if entry != nil {
|
||||
var storedCache configCache
|
||||
if err := entry.DecodeJSON(&storedCache); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
size = storedCache.Size
|
||||
}
|
||||
return size, nil
|
||||
}
|
||||
|
||||
func (b *backend) invalidate(_ context.Context, key string) {
|
||||
if b.Logger().IsDebug() {
|
||||
b.Logger().Debug("invalidating key", "key", key)
|
||||
|
||||
@ -30,7 +30,7 @@ func createBackendWithStorage(t *testing.T) (*backend, logical.Storage) {
|
||||
config := logical.TestBackendConfig()
|
||||
config.StorageView = &logical.InmemStorage{}
|
||||
|
||||
b := Backend(config)
|
||||
b, _ := Backend(context.Background(), config)
|
||||
if b == nil {
|
||||
t.Fatalf("failed to create backend")
|
||||
}
|
||||
@ -50,7 +50,7 @@ func createBackendWithSysView(t *testing.T) (*backend, logical.Storage) {
|
||||
System: sysView,
|
||||
}
|
||||
|
||||
b := Backend(conf)
|
||||
b, _ := Backend(context.Background(), conf)
|
||||
if b == nil {
|
||||
t.Fatal("failed to create backend")
|
||||
}
|
||||
@ -63,6 +63,49 @@ func createBackendWithSysView(t *testing.T) (*backend, logical.Storage) {
|
||||
return b, storage
|
||||
}
|
||||
|
||||
func createBackendWithSysViewWithStorage(t *testing.T, s logical.Storage) *backend {
|
||||
sysView := logical.TestSystemView()
|
||||
|
||||
conf := &logical.BackendConfig{
|
||||
StorageView: s,
|
||||
System: sysView,
|
||||
}
|
||||
|
||||
b, _ := Backend(context.Background(), conf)
|
||||
if b == nil {
|
||||
t.Fatal("failed to create backend")
|
||||
}
|
||||
|
||||
err := b.Backend.Setup(context.Background(), conf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func createBackendWithForceNoCacheWithSysViewWithStorage(t *testing.T, s logical.Storage) *backend {
|
||||
sysView := logical.TestSystemView()
|
||||
sysView.CachingDisabledVal = true
|
||||
|
||||
conf := &logical.BackendConfig{
|
||||
StorageView: s,
|
||||
System: sysView,
|
||||
}
|
||||
|
||||
b, _ := Backend(context.Background(), conf)
|
||||
if b == nil {
|
||||
t.Fatal("failed to create backend")
|
||||
}
|
||||
|
||||
err := b.Backend.Setup(context.Background(), conf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func TestTransit_RSA(t *testing.T) {
|
||||
testTransit_RSA(t, "rsa-2048")
|
||||
testTransit_RSA(t, "rsa-4096")
|
||||
@ -1294,16 +1337,17 @@ func testConvergentEncryptionCommon(t *testing.T, ver int, keyType keysutil.KeyT
|
||||
func TestPolicyFuzzing(t *testing.T) {
|
||||
var be *backend
|
||||
sysView := logical.TestSystemView()
|
||||
sysView.CachingDisabledVal = true
|
||||
conf := &logical.BackendConfig{
|
||||
System: sysView,
|
||||
}
|
||||
|
||||
be = Backend(conf)
|
||||
be, _ = Backend(context.Background(), conf)
|
||||
be.Setup(context.Background(), conf)
|
||||
testPolicyFuzzingCommon(t, be)
|
||||
|
||||
sysView.CachingDisabledVal = true
|
||||
be = Backend(conf)
|
||||
be, _ = Backend(context.Background(), conf)
|
||||
be.Setup(context.Background(), conf)
|
||||
testPolicyFuzzingCommon(t, be)
|
||||
}
|
||||
|
||||
106
builtin/logical/transit/path_cache_config.go
Normal file
106
builtin/logical/transit/path_cache_config.go
Normal file
@ -0,0 +1,106 @@
|
||||
package transit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/hashicorp/vault/sdk/framework"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
)
|
||||
|
||||
func (b *backend) pathCacheConfig() *framework.Path {
|
||||
return &framework.Path{
|
||||
Pattern: "cache-config",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"size": &framework.FieldSchema{
|
||||
Type: framework.TypeInt,
|
||||
Required: false,
|
||||
Default: 0,
|
||||
Description: `Size of cache, use 0 for an unlimited cache size, defaults to 0`,
|
||||
},
|
||||
},
|
||||
|
||||
Operations: map[logical.Operation]framework.OperationHandler{
|
||||
logical.ReadOperation: &framework.PathOperation{
|
||||
Callback: b.pathCacheConfigRead,
|
||||
Summary: "Returns the size of the active cache",
|
||||
},
|
||||
|
||||
logical.UpdateOperation: &framework.PathOperation{
|
||||
Callback: b.pathCacheConfigWrite,
|
||||
Summary: "Configures a new cache of the specified size",
|
||||
},
|
||||
|
||||
logical.CreateOperation: &framework.PathOperation{
|
||||
Callback: b.pathCacheConfigWrite,
|
||||
Summary: "Configures a new cache of the specified size",
|
||||
},
|
||||
},
|
||||
|
||||
HelpSynopsis: pathCacheConfigHelpSyn,
|
||||
HelpDescription: pathCacheConfigHelpDesc,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *backend) pathCacheConfigWrite(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
// get target size
|
||||
cacheSize := d.Get("size").(int)
|
||||
if cacheSize < 0 {
|
||||
return logical.ErrorResponse("size must be greater or equal to 0"), logical.ErrInvalidRequest
|
||||
}
|
||||
|
||||
// store cache size
|
||||
entry, err := logical.StorageEntryJSON("config/cache", &configCache{
|
||||
Size: cacheSize,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := req.Storage.Put(ctx, entry); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := &logical.Response{
|
||||
Warnings: []string{"cache configurations will be applied when this backend is restarted"},
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
type configCache struct {
|
||||
Size int `json:"size"`
|
||||
}
|
||||
|
||||
func (b *backend) pathCacheConfigRead(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
// error if no cache is configured
|
||||
if !b.lm.GetUseCache() {
|
||||
return nil, errors.New(
|
||||
"caching is disabled for this transit mount",
|
||||
)
|
||||
}
|
||||
|
||||
// Compare current and stored cache sizes. If they are different warn the user.
|
||||
currentCacheSize := b.lm.GetCacheSize()
|
||||
storedCacheSize, err := GetCacheSizeFromStorage(ctx, req.Storage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := &logical.Response{
|
||||
Data: map[string]interface{}{
|
||||
"size": storedCacheSize,
|
||||
},
|
||||
}
|
||||
|
||||
if currentCacheSize != storedCacheSize {
|
||||
resp.Warnings = []string{"This cache size will not be applied until the transit mount is reloaded"}
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
const pathCacheConfigHelpSyn = `Configure caching strategy`
|
||||
|
||||
const pathCacheConfigHelpDesc = `
|
||||
This path is used to configure and query the cache size of the active cache, a size of 0 means unlimited.
|
||||
`
|
||||
80
builtin/logical/transit/path_cache_config_test.go
Normal file
80
builtin/logical/transit/path_cache_config_test.go
Normal file
@ -0,0 +1,80 @@
|
||||
package transit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
)
|
||||
|
||||
const targetCacheSize = 12345
|
||||
|
||||
func TestTransit_CacheConfig(t *testing.T) {
|
||||
b1, storage := createBackendWithSysView(t)
|
||||
|
||||
doReq := func(b *backend, req *logical.Request) *logical.Response {
|
||||
resp, err := b.HandleRequest(context.Background(), req)
|
||||
if err != nil || (resp != nil && resp.IsError()) {
|
||||
t.Fatalf("got err:\n%#v\nreq:\n%#v\n", err, *req)
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
doErrReq := func(b *backend, req *logical.Request) {
|
||||
resp, err := b.HandleRequest(context.Background(), req)
|
||||
if err == nil {
|
||||
if resp == nil || !resp.IsError() {
|
||||
t.Fatalf("expected error; req:\n%#v\n", *req)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
validateResponse := func(resp *logical.Response, expectedCacheSize int, expectedWarning bool) {
|
||||
actualCacheSize, ok := resp.Data["size"].(int)
|
||||
if !ok {
|
||||
t.Fatalf("No size returned")
|
||||
}
|
||||
if expectedCacheSize != actualCacheSize {
|
||||
t.Fatalf("testAccReadCacheConfig expected: %d got: %d", expectedCacheSize, actualCacheSize)
|
||||
}
|
||||
// check for the presence/absence of warnings - warnings are expected if a cache size has been
|
||||
// configured but not yet applied by reloading the plugin
|
||||
warningCheckPass := expectedWarning == (len(resp.Warnings) > 0)
|
||||
if !warningCheckPass {
|
||||
t.Fatalf(
|
||||
"testAccSteporeadCacheConfig warnings error.\n"+
|
||||
"expect warnings: %t but number of warnings was: %d",
|
||||
expectedWarning, len(resp.Warnings),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
writeReq := &logical.Request{
|
||||
Storage: storage,
|
||||
Operation: logical.UpdateOperation,
|
||||
Path: "cache-config",
|
||||
Data: map[string]interface{}{
|
||||
"size": targetCacheSize,
|
||||
},
|
||||
}
|
||||
|
||||
readReq := &logical.Request{
|
||||
Storage: storage,
|
||||
Operation: logical.ReadOperation,
|
||||
Path: "cache-config",
|
||||
}
|
||||
|
||||
// test steps
|
||||
// b1 should spin up with an unlimited cache
|
||||
validateResponse(doReq(b1, readReq), 0, false)
|
||||
doReq(b1, writeReq)
|
||||
validateResponse(doReq(b1, readReq), targetCacheSize, true)
|
||||
|
||||
// b2 should spin up with a configured cache
|
||||
b2 := createBackendWithSysViewWithStorage(t, storage)
|
||||
validateResponse(doReq(b2, readReq), targetCacheSize, false)
|
||||
|
||||
// b3 enables transit without a cache, trying to read it should error
|
||||
b3 := createBackendWithForceNoCacheWithSysViewWithStorage(t, storage)
|
||||
doErrReq(b3, readReq)
|
||||
}
|
||||
@ -14,8 +14,9 @@ func TestTransit_Random(t *testing.T) {
|
||||
var b *backend
|
||||
sysView := logical.TestSystemView()
|
||||
storage := &logical.InmemStorage{}
|
||||
sysView.CachingDisabledVal = true
|
||||
|
||||
b = Backend(&logical.BackendConfig{
|
||||
b, _ = Backend(context.Background(), &logical.BackendConfig{
|
||||
StorageView: storage,
|
||||
System: sysView,
|
||||
})
|
||||
|
||||
8
sdk/helper/keysutil/cache.go
Normal file
8
sdk/helper/keysutil/cache.go
Normal file
@ -0,0 +1,8 @@
|
||||
package keysutil
|
||||
|
||||
type Cache interface {
|
||||
Delete(key interface{})
|
||||
Load(key interface{}) (value interface{}, ok bool)
|
||||
Store(key, value interface{})
|
||||
Size() int
|
||||
}
|
||||
@ -55,21 +55,44 @@ type PolicyRequest struct {
|
||||
|
||||
type LockManager struct {
|
||||
useCache bool
|
||||
// If caching is enabled, the map of name to in-memory policy cache
|
||||
cache sync.Map
|
||||
|
||||
cache Cache
|
||||
keyLocks []*locksutil.LockEntry
|
||||
}
|
||||
|
||||
func NewLockManager(cacheDisabled bool) *LockManager {
|
||||
func NewLockManager(useCache bool, cacheSize int) (*LockManager, error) {
|
||||
// determine the type of cache to create
|
||||
var cache Cache
|
||||
switch {
|
||||
case !useCache:
|
||||
case cacheSize < 0:
|
||||
return nil, errors.New("cache size must be greater or equal to zero")
|
||||
case cacheSize == 0:
|
||||
cache = NewTransitSyncMap()
|
||||
case cacheSize > 0:
|
||||
newLRUCache, err := NewTransitLRU(cacheSize)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("failed to create cache: {{err}}", err)
|
||||
}
|
||||
cache = newLRUCache
|
||||
}
|
||||
|
||||
lm := &LockManager{
|
||||
useCache: !cacheDisabled,
|
||||
useCache: useCache,
|
||||
cache: cache,
|
||||
keyLocks: locksutil.CreateLocks(),
|
||||
}
|
||||
return lm
|
||||
|
||||
return lm, nil
|
||||
}
|
||||
|
||||
func (lm *LockManager) CacheActive() bool {
|
||||
func (lm *LockManager) GetCacheSize() int {
|
||||
if !lm.useCache {
|
||||
return 0
|
||||
}
|
||||
return lm.cache.Size()
|
||||
}
|
||||
|
||||
func (lm *LockManager) GetUseCache() bool {
|
||||
return lm.useCache
|
||||
}
|
||||
|
||||
@ -178,7 +201,6 @@ func (lm *LockManager) RestorePolicy(ctx context.Context, storage logical.Storag
|
||||
if lm.useCache {
|
||||
lm.cache.Store(name, keyData.Policy)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -186,7 +208,7 @@ func (lm *LockManager) BackupPolicy(ctx context.Context, storage logical.Storage
|
||||
var p *Policy
|
||||
var err error
|
||||
|
||||
// Backup writes information about when the bacup took place, so we get an
|
||||
// Backup writes information about when the backup took place, so we get an
|
||||
// exclusive lock here
|
||||
lock := locksutil.LockForKey(lm.keyLocks, name)
|
||||
lock.Lock()
|
||||
|
||||
@ -52,8 +52,10 @@ func TestPolicy_KeyEntryMapUpgrade(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_KeyUpgrade(t *testing.T) {
|
||||
testKeyUpgradeCommon(t, NewLockManager(false))
|
||||
testKeyUpgradeCommon(t, NewLockManager(true))
|
||||
lockManagerWithCache, _ := NewLockManager(true, 0)
|
||||
lockManagerWithoutCache, _ := NewLockManager(false, 0)
|
||||
testKeyUpgradeCommon(t, lockManagerWithCache)
|
||||
testKeyUpgradeCommon(t, lockManagerWithoutCache)
|
||||
}
|
||||
|
||||
func testKeyUpgradeCommon(t *testing.T, lm *LockManager) {
|
||||
@ -97,8 +99,10 @@ func testKeyUpgradeCommon(t *testing.T, lm *LockManager) {
|
||||
}
|
||||
|
||||
func Test_ArchivingUpgrade(t *testing.T) {
|
||||
testArchivingUpgradeCommon(t, NewLockManager(false))
|
||||
testArchivingUpgradeCommon(t, NewLockManager(true))
|
||||
lockManagerWithCache, _ := NewLockManager(true, 0)
|
||||
lockManagerWithoutCache, _ := NewLockManager(false, 0)
|
||||
testArchivingUpgradeCommon(t, lockManagerWithCache)
|
||||
testArchivingUpgradeCommon(t, lockManagerWithoutCache)
|
||||
}
|
||||
|
||||
func testArchivingUpgradeCommon(t *testing.T, lm *LockManager) {
|
||||
@ -255,8 +259,10 @@ func testArchivingUpgradeCommon(t *testing.T, lm *LockManager) {
|
||||
}
|
||||
|
||||
func Test_Archiving(t *testing.T) {
|
||||
testArchivingCommon(t, NewLockManager(false))
|
||||
testArchivingCommon(t, NewLockManager(true))
|
||||
lockManagerWithCache, _ := NewLockManager(true, 0)
|
||||
lockManagerWithoutCache, _ := NewLockManager(false, 0)
|
||||
testArchivingUpgradeCommon(t, lockManagerWithCache)
|
||||
testArchivingUpgradeCommon(t, lockManagerWithoutCache)
|
||||
}
|
||||
|
||||
func testArchivingCommon(t *testing.T, lm *LockManager) {
|
||||
@ -420,7 +426,7 @@ func checkKeys(t *testing.T,
|
||||
|
||||
func Test_StorageErrorSafety(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
lm := NewLockManager(false)
|
||||
lm, _ := NewLockManager(true, 0)
|
||||
|
||||
storage := &logical.InmemStorage{}
|
||||
p, _, err := lm.GetPolicy(ctx, PolicyRequest{
|
||||
@ -468,7 +474,7 @@ func Test_StorageErrorSafety(t *testing.T) {
|
||||
|
||||
func Test_BadUpgrade(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
lm := NewLockManager(false)
|
||||
lm, _ := NewLockManager(true, 0)
|
||||
storage := &logical.InmemStorage{}
|
||||
p, _, err := lm.GetPolicy(ctx, PolicyRequest{
|
||||
Upsert: true,
|
||||
@ -533,7 +539,7 @@ func Test_BadUpgrade(t *testing.T) {
|
||||
|
||||
func Test_BadArchive(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
lm := NewLockManager(false)
|
||||
lm, _ := NewLockManager(true, 0)
|
||||
storage := &logical.InmemStorage{}
|
||||
p, _, err := lm.GetPolicy(ctx, PolicyRequest{
|
||||
Upsert: true,
|
||||
|
||||
29
sdk/helper/keysutil/transit_lru.go
Normal file
29
sdk/helper/keysutil/transit_lru.go
Normal file
@ -0,0 +1,29 @@
|
||||
package keysutil
|
||||
|
||||
import lru "github.com/hashicorp/golang-lru"
|
||||
|
||||
type TransitLRU struct {
|
||||
size int
|
||||
lru *lru.TwoQueueCache
|
||||
}
|
||||
|
||||
func NewTransitLRU(size int) (*TransitLRU, error) {
|
||||
lru, err := lru.New2Q(size)
|
||||
return &TransitLRU{lru: lru, size: size}, err
|
||||
}
|
||||
|
||||
func (c *TransitLRU) Delete(key interface{}) {
|
||||
c.lru.Remove(key)
|
||||
}
|
||||
|
||||
func (c *TransitLRU) Load(key interface{}) (value interface{}, ok bool) {
|
||||
return c.lru.Get(key)
|
||||
}
|
||||
|
||||
func (c *TransitLRU) Store(key, value interface{}) {
|
||||
c.lru.Add(key, value)
|
||||
}
|
||||
|
||||
func (c *TransitLRU) Size() int {
|
||||
return c.size
|
||||
}
|
||||
29
sdk/helper/keysutil/transit_syncmap.go
Normal file
29
sdk/helper/keysutil/transit_syncmap.go
Normal file
@ -0,0 +1,29 @@
|
||||
package keysutil
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type TransitSyncMap struct {
|
||||
syncmap sync.Map
|
||||
}
|
||||
|
||||
func NewTransitSyncMap() *TransitSyncMap {
|
||||
return &TransitSyncMap{syncmap: sync.Map{}}
|
||||
}
|
||||
|
||||
func (c *TransitSyncMap) Delete(key interface{}) {
|
||||
c.syncmap.Delete(key)
|
||||
}
|
||||
|
||||
func (c *TransitSyncMap) Load(key interface{}) (value interface{}, ok bool) {
|
||||
return c.syncmap.Load(key)
|
||||
}
|
||||
|
||||
func (c *TransitSyncMap) Store(key, value interface{}) {
|
||||
c.syncmap.Store(key, value)
|
||||
}
|
||||
|
||||
func (c *TransitSyncMap) Size() int {
|
||||
return 0
|
||||
}
|
||||
8
vendor/github.com/hashicorp/vault/sdk/helper/keysutil/cache.go
generated
vendored
Normal file
8
vendor/github.com/hashicorp/vault/sdk/helper/keysutil/cache.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
package keysutil
|
||||
|
||||
type Cache interface {
|
||||
Delete(key interface{})
|
||||
Load(key interface{}) (value interface{}, ok bool)
|
||||
Store(key, value interface{})
|
||||
Size() int
|
||||
}
|
||||
40
vendor/github.com/hashicorp/vault/sdk/helper/keysutil/lock_manager.go
generated
vendored
40
vendor/github.com/hashicorp/vault/sdk/helper/keysutil/lock_manager.go
generated
vendored
@ -55,21 +55,44 @@ type PolicyRequest struct {
|
||||
|
||||
type LockManager struct {
|
||||
useCache bool
|
||||
// If caching is enabled, the map of name to in-memory policy cache
|
||||
cache sync.Map
|
||||
|
||||
cache Cache
|
||||
keyLocks []*locksutil.LockEntry
|
||||
}
|
||||
|
||||
func NewLockManager(cacheDisabled bool) *LockManager {
|
||||
func NewLockManager(useCache bool, cacheSize int) (*LockManager, error) {
|
||||
// determine the type of cache to create
|
||||
var cache Cache
|
||||
switch {
|
||||
case !useCache:
|
||||
case cacheSize < 0:
|
||||
return nil, errors.New("cache size must be greater or equal to zero")
|
||||
case cacheSize == 0:
|
||||
cache = NewTransitSyncMap()
|
||||
case cacheSize > 0:
|
||||
newLRUCache, err := NewTransitLRU(cacheSize)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("failed to create cache: {{err}}", err)
|
||||
}
|
||||
cache = newLRUCache
|
||||
}
|
||||
|
||||
lm := &LockManager{
|
||||
useCache: !cacheDisabled,
|
||||
useCache: useCache,
|
||||
cache: cache,
|
||||
keyLocks: locksutil.CreateLocks(),
|
||||
}
|
||||
return lm
|
||||
|
||||
return lm, nil
|
||||
}
|
||||
|
||||
func (lm *LockManager) CacheActive() bool {
|
||||
func (lm *LockManager) GetCacheSize() int {
|
||||
if !lm.useCache {
|
||||
return 0
|
||||
}
|
||||
return lm.cache.Size()
|
||||
}
|
||||
|
||||
func (lm *LockManager) GetUseCache() bool {
|
||||
return lm.useCache
|
||||
}
|
||||
|
||||
@ -178,7 +201,6 @@ func (lm *LockManager) RestorePolicy(ctx context.Context, storage logical.Storag
|
||||
if lm.useCache {
|
||||
lm.cache.Store(name, keyData.Policy)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -186,7 +208,7 @@ func (lm *LockManager) BackupPolicy(ctx context.Context, storage logical.Storage
|
||||
var p *Policy
|
||||
var err error
|
||||
|
||||
// Backup writes information about when the bacup took place, so we get an
|
||||
// Backup writes information about when the backup took place, so we get an
|
||||
// exclusive lock here
|
||||
lock := locksutil.LockForKey(lm.keyLocks, name)
|
||||
lock.Lock()
|
||||
|
||||
29
vendor/github.com/hashicorp/vault/sdk/helper/keysutil/transit_lru.go
generated
vendored
Normal file
29
vendor/github.com/hashicorp/vault/sdk/helper/keysutil/transit_lru.go
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
package keysutil
|
||||
|
||||
import lru "github.com/hashicorp/golang-lru"
|
||||
|
||||
type TransitLRU struct {
|
||||
size int
|
||||
lru *lru.TwoQueueCache
|
||||
}
|
||||
|
||||
func NewTransitLRU(size int) (*TransitLRU, error) {
|
||||
lru, err := lru.New2Q(size)
|
||||
return &TransitLRU{lru: lru, size: size}, err
|
||||
}
|
||||
|
||||
func (c *TransitLRU) Delete(key interface{}) {
|
||||
c.lru.Remove(key)
|
||||
}
|
||||
|
||||
func (c *TransitLRU) Load(key interface{}) (value interface{}, ok bool) {
|
||||
return c.lru.Get(key)
|
||||
}
|
||||
|
||||
func (c *TransitLRU) Store(key, value interface{}) {
|
||||
c.lru.Add(key, value)
|
||||
}
|
||||
|
||||
func (c *TransitLRU) Size() int {
|
||||
return c.size
|
||||
}
|
||||
29
vendor/github.com/hashicorp/vault/sdk/helper/keysutil/transit_syncmap.go
generated
vendored
Normal file
29
vendor/github.com/hashicorp/vault/sdk/helper/keysutil/transit_syncmap.go
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
package keysutil
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type TransitSyncMap struct {
|
||||
syncmap sync.Map
|
||||
}
|
||||
|
||||
func NewTransitSyncMap() *TransitSyncMap {
|
||||
return &TransitSyncMap{syncmap: sync.Map{}}
|
||||
}
|
||||
|
||||
func (c *TransitSyncMap) Delete(key interface{}) {
|
||||
c.syncmap.Delete(key)
|
||||
}
|
||||
|
||||
func (c *TransitSyncMap) Load(key interface{}) (value interface{}, ok bool) {
|
||||
return c.syncmap.Load(key)
|
||||
}
|
||||
|
||||
func (c *TransitSyncMap) Store(key, value interface{}) {
|
||||
c.syncmap.Store(key, value)
|
||||
}
|
||||
|
||||
func (c *TransitSyncMap) Size() int {
|
||||
return 0
|
||||
}
|
||||
@ -1252,3 +1252,64 @@ $ curl \
|
||||
--data @payload.json \
|
||||
http://127.0.0.1:8200/v1/transit/keys/my-key/trim
|
||||
```
|
||||
|
||||
## Configure Cache
|
||||
|
||||
This endpoint is used to configure the transit engine's cache. Note that configuration
|
||||
changes will not be applied until the transit plugin is reloaded which can be achieved
|
||||
using the [`/sys/plugins/reload/backend`][sys-plugin-reload-backend] endpoint.
|
||||
|
||||
| Method | Path |
|
||||
| :------------------------- | :--------------------- |
|
||||
| `POST` | `/transit/cache-config` |
|
||||
|
||||
### Parameters
|
||||
|
||||
- `size` `(int: 0)` - Specifies the size in terms of number of entries. A size of
|
||||
`0` means unlimited. A _Least Recently Used_ (LRU) caching strategy is used for a
|
||||
non-zero cache size.
|
||||
|
||||
### Sample Payload
|
||||
|
||||
```json
|
||||
{
|
||||
"size": 456
|
||||
}
|
||||
```
|
||||
|
||||
### Sample Request
|
||||
|
||||
```
|
||||
$ curl \
|
||||
--header "X-Vault-Token: ..."
|
||||
--request POST \
|
||||
--data @payload.json \
|
||||
http://127.0.0.1:8200/v1/transit/cache-config
|
||||
```
|
||||
|
||||
## Read Transit Cache Configuration
|
||||
|
||||
This endpoint retrieves configurations for the transit engine's cache.
|
||||
|
||||
| Method | Path |
|
||||
| :------------------------- | :--------------------- |
|
||||
| `GET` | `/transit/cache-config` |
|
||||
|
||||
### Sample Request
|
||||
|
||||
```
|
||||
$ curl \
|
||||
--header "X-Vault-Token: ..."
|
||||
--request GET \
|
||||
http://127.0.0.1:8200/v1/transit/cache-config
|
||||
```
|
||||
|
||||
### Sample Response
|
||||
|
||||
```json
|
||||
"data": {
|
||||
"size": 0
|
||||
},
|
||||
```
|
||||
|
||||
[sys-plugin-reload-backend]: /api/system/plugins-reload-backend.html#reload-plugins
|
||||
Loading…
x
Reference in New Issue
Block a user