From 4ed616dacb83a91fdfea52f040fe7dfbed6a429c Mon Sep 17 00:00:00 2001 From: Lexman Date: Tue, 4 Jun 2019 15:40:56 -0700 Subject: [PATCH] =?UTF-8?q?transit=20cache=20is=20an=20Interface=20impleme?= =?UTF-8?q?nted=20by=20wrapped=20versions=20of=20sync=E2=80=A6=20(#6225)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 * 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 --- builtin/logical/transit/backend.go | 45 +++++++- builtin/logical/transit/backend_test.go | 52 ++++++++- builtin/logical/transit/path_cache_config.go | 106 ++++++++++++++++++ .../logical/transit/path_cache_config_test.go | 80 +++++++++++++ builtin/logical/transit/path_random_test.go | 3 +- sdk/helper/keysutil/cache.go | 8 ++ sdk/helper/keysutil/lock_manager.go | 40 +++++-- sdk/helper/keysutil/policy_test.go | 24 ++-- sdk/helper/keysutil/transit_lru.go | 29 +++++ sdk/helper/keysutil/transit_syncmap.go | 29 +++++ .../vault/sdk/helper/keysutil/cache.go | 8 ++ .../vault/sdk/helper/keysutil/lock_manager.go | 40 +++++-- .../vault/sdk/helper/keysutil/transit_lru.go | 29 +++++ .../sdk/helper/keysutil/transit_syncmap.go | 29 +++++ .../source/api/secret/transit/index.html.md | 61 ++++++++++ 15 files changed, 547 insertions(+), 36 deletions(-) create mode 100644 builtin/logical/transit/path_cache_config.go create mode 100644 builtin/logical/transit/path_cache_config_test.go create mode 100644 sdk/helper/keysutil/cache.go create mode 100644 sdk/helper/keysutil/transit_lru.go create mode 100644 sdk/helper/keysutil/transit_syncmap.go create mode 100644 vendor/github.com/hashicorp/vault/sdk/helper/keysutil/cache.go create mode 100644 vendor/github.com/hashicorp/vault/sdk/helper/keysutil/transit_lru.go create mode 100644 vendor/github.com/hashicorp/vault/sdk/helper/keysutil/transit_syncmap.go diff --git a/builtin/logical/transit/backend.go b/builtin/logical/transit/backend.go index 58fb5910d1..9d8d43b38f 100644 --- a/builtin/logical/transit/backend.go +++ b/builtin/logical/transit/backend.go @@ -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) diff --git a/builtin/logical/transit/backend_test.go b/builtin/logical/transit/backend_test.go index 800fbf4de0..db103782e0 100644 --- a/builtin/logical/transit/backend_test.go +++ b/builtin/logical/transit/backend_test.go @@ -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) } diff --git a/builtin/logical/transit/path_cache_config.go b/builtin/logical/transit/path_cache_config.go new file mode 100644 index 0000000000..3351249691 --- /dev/null +++ b/builtin/logical/transit/path_cache_config.go @@ -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. +` diff --git a/builtin/logical/transit/path_cache_config_test.go b/builtin/logical/transit/path_cache_config_test.go new file mode 100644 index 0000000000..6cca1b2656 --- /dev/null +++ b/builtin/logical/transit/path_cache_config_test.go @@ -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) +} diff --git a/builtin/logical/transit/path_random_test.go b/builtin/logical/transit/path_random_test.go index 260b22f573..0b59d76c65 100644 --- a/builtin/logical/transit/path_random_test.go +++ b/builtin/logical/transit/path_random_test.go @@ -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, }) diff --git a/sdk/helper/keysutil/cache.go b/sdk/helper/keysutil/cache.go new file mode 100644 index 0000000000..7da9c202fa --- /dev/null +++ b/sdk/helper/keysutil/cache.go @@ -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 +} diff --git a/sdk/helper/keysutil/lock_manager.go b/sdk/helper/keysutil/lock_manager.go index 95064ff7a8..123742ccc5 100644 --- a/sdk/helper/keysutil/lock_manager.go +++ b/sdk/helper/keysutil/lock_manager.go @@ -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() diff --git a/sdk/helper/keysutil/policy_test.go b/sdk/helper/keysutil/policy_test.go index 20f71c5aed..79b50a3c14 100644 --- a/sdk/helper/keysutil/policy_test.go +++ b/sdk/helper/keysutil/policy_test.go @@ -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, diff --git a/sdk/helper/keysutil/transit_lru.go b/sdk/helper/keysutil/transit_lru.go new file mode 100644 index 0000000000..cd1f6dafe6 --- /dev/null +++ b/sdk/helper/keysutil/transit_lru.go @@ -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 +} diff --git a/sdk/helper/keysutil/transit_syncmap.go b/sdk/helper/keysutil/transit_syncmap.go new file mode 100644 index 0000000000..ce9071380a --- /dev/null +++ b/sdk/helper/keysutil/transit_syncmap.go @@ -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 +} diff --git a/vendor/github.com/hashicorp/vault/sdk/helper/keysutil/cache.go b/vendor/github.com/hashicorp/vault/sdk/helper/keysutil/cache.go new file mode 100644 index 0000000000..7da9c202fa --- /dev/null +++ b/vendor/github.com/hashicorp/vault/sdk/helper/keysutil/cache.go @@ -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 +} diff --git a/vendor/github.com/hashicorp/vault/sdk/helper/keysutil/lock_manager.go b/vendor/github.com/hashicorp/vault/sdk/helper/keysutil/lock_manager.go index 95064ff7a8..123742ccc5 100644 --- a/vendor/github.com/hashicorp/vault/sdk/helper/keysutil/lock_manager.go +++ b/vendor/github.com/hashicorp/vault/sdk/helper/keysutil/lock_manager.go @@ -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() diff --git a/vendor/github.com/hashicorp/vault/sdk/helper/keysutil/transit_lru.go b/vendor/github.com/hashicorp/vault/sdk/helper/keysutil/transit_lru.go new file mode 100644 index 0000000000..cd1f6dafe6 --- /dev/null +++ b/vendor/github.com/hashicorp/vault/sdk/helper/keysutil/transit_lru.go @@ -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 +} diff --git a/vendor/github.com/hashicorp/vault/sdk/helper/keysutil/transit_syncmap.go b/vendor/github.com/hashicorp/vault/sdk/helper/keysutil/transit_syncmap.go new file mode 100644 index 0000000000..ce9071380a --- /dev/null +++ b/vendor/github.com/hashicorp/vault/sdk/helper/keysutil/transit_syncmap.go @@ -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 +} diff --git a/website/source/api/secret/transit/index.html.md b/website/source/api/secret/transit/index.html.md index a4bbc58695..4a24047963 100644 --- a/website/source/api/secret/transit/index.html.md +++ b/website/source/api/secret/transit/index.html.md @@ -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 \ No newline at end of file