mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 18:48:08 +00:00 
			
		
		
		
	Enforce minimum cache size for transit backend (#12418)
* Enforce Minimum cache size for transit backend * enfore minimum cache size and log a warning during backend construction * Update documentation for transit backend cache configuration * Added changelog * Addressed review feedback and added unit test * Modify code in pathCacheConfigWrite to make use of the updated cache size * Updated code to refresh cache size on transit backend without restart * Update code to acquire read and write locks appropriately
This commit is contained in:
		| @@ -3,13 +3,18 @@ package transit | |||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"io" | ||||||
| 	"strings" | 	"strings" | ||||||
|  | 	"sync" | ||||||
|  |  | ||||||
| 	"github.com/hashicorp/vault/sdk/framework" | 	"github.com/hashicorp/vault/sdk/framework" | ||||||
| 	"github.com/hashicorp/vault/sdk/helper/keysutil" | 	"github.com/hashicorp/vault/sdk/helper/keysutil" | ||||||
| 	"github.com/hashicorp/vault/sdk/logical" | 	"github.com/hashicorp/vault/sdk/logical" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // Minimum cache size for transit backend | ||||||
|  | const minCacheSize = 10 | ||||||
|  |  | ||||||
| func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) { | func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) { | ||||||
| 	b, err := Backend(ctx, conf) | 	b, err := Backend(ctx, conf) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @@ -68,6 +73,11 @@ func Backend(ctx context.Context, conf *logical.BackendConfig) (*backend, error) | |||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, fmt.Errorf("Error retrieving cache size from storage: %w", err) | 			return nil, fmt.Errorf("Error retrieving cache size from storage: %w", err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		if cacheSize != 0 && cacheSize < minCacheSize { | ||||||
|  | 			b.Logger().Warn("size %d is less than minimum %d. Cache size is set to %d", cacheSize, minCacheSize, minCacheSize) | ||||||
|  | 			cacheSize = minCacheSize | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var err error | 	var err error | ||||||
| @@ -82,6 +92,9 @@ func Backend(ctx context.Context, conf *logical.BackendConfig) (*backend, error) | |||||||
| type backend struct { | type backend struct { | ||||||
| 	*framework.Backend | 	*framework.Backend | ||||||
| 	lm *keysutil.LockManager | 	lm *keysutil.LockManager | ||||||
|  | 	// Lock to make changes to any of the backend's cache configuration. | ||||||
|  | 	configMutex sync.RWMutex | ||||||
|  | 	cacheSizeChanged bool | ||||||
| } | } | ||||||
|  |  | ||||||
| func GetCacheSizeFromStorage(ctx context.Context, s logical.Storage) (int, error) { | func GetCacheSizeFromStorage(ctx context.Context, s logical.Storage) (int, error) { | ||||||
| @@ -100,7 +113,37 @@ func GetCacheSizeFromStorage(ctx context.Context, s logical.Storage) (int, error | |||||||
| 	return size, nil | 	return size, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (b *backend) invalidate(_ context.Context, key string) { | // Update cache size and get policy | ||||||
|  | func (b *backend) GetPolicy(ctx context.Context, polReq keysutil.PolicyRequest, rand io.Reader) (retP *keysutil.Policy, retUpserted bool, retErr error) { | ||||||
|  | 	// Acquire read lock to read cacheSizeChanged | ||||||
|  | 	b.configMutex.RLock() | ||||||
|  | 	if b.lm.GetUseCache() && b.cacheSizeChanged { | ||||||
|  | 		var err error | ||||||
|  | 		currentCacheSize := b.lm.GetCacheSize() | ||||||
|  | 		storedCacheSize, err := GetCacheSizeFromStorage(ctx, polReq.Storage) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, false, err | ||||||
|  | 		} | ||||||
|  | 		if currentCacheSize != storedCacheSize { | ||||||
|  | 			err = b.lm.InitCache(storedCacheSize) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return nil, false, err | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		// Release the read lock and acquire the write lock | ||||||
|  | 		b.configMutex.RUnlock() | ||||||
|  | 		b.configMutex.Lock() | ||||||
|  | 		defer b.configMutex.Unlock() | ||||||
|  | 		b.cacheSizeChanged = false | ||||||
|  | 	} | ||||||
|  | 	p, _, err := b.lm.GetPolicy(ctx, polReq, rand) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return p, false, err | ||||||
|  | 	} | ||||||
|  | 	return p, true, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (b *backend) invalidate(ctx context.Context, key string) { | ||||||
| 	if b.Logger().IsDebug() { | 	if b.Logger().IsDebug() { | ||||||
| 		b.Logger().Debug("invalidating key", "key", key) | 		b.Logger().Debug("invalidating key", "key", key) | ||||||
| 	} | 	} | ||||||
| @@ -108,5 +151,10 @@ func (b *backend) invalidate(_ context.Context, key string) { | |||||||
| 	case strings.HasPrefix(key, "policy/"): | 	case strings.HasPrefix(key, "policy/"): | ||||||
| 		name := strings.TrimPrefix(key, "policy/") | 		name := strings.TrimPrefix(key, "policy/") | ||||||
| 		b.lm.InvalidatePolicy(name) | 		b.lm.InvalidatePolicy(name) | ||||||
|  | 	case strings.HasPrefix(key, "cache-config/"): | ||||||
|  | 		// Acquire the lock to set the flag to indicate that cache size needs to be refreshed from storage | ||||||
|  | 		b.configMutex.Lock() | ||||||
|  | 		defer b.configMutex.Unlock() | ||||||
|  | 		b.cacheSizeChanged = true | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -3,7 +3,6 @@ package transit | |||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"errors" | 	"errors" | ||||||
|  |  | ||||||
| 	"github.com/hashicorp/vault/sdk/framework" | 	"github.com/hashicorp/vault/sdk/framework" | ||||||
| 	"github.com/hashicorp/vault/sdk/logical" | 	"github.com/hashicorp/vault/sdk/logical" | ||||||
| ) | ) | ||||||
| @@ -45,8 +44,8 @@ func (b *backend) pathCacheConfig() *framework.Path { | |||||||
| func (b *backend) pathCacheConfigWrite(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { | func (b *backend) pathCacheConfigWrite(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { | ||||||
| 	// get target size | 	// get target size | ||||||
| 	cacheSize := d.Get("size").(int) | 	cacheSize := d.Get("size").(int) | ||||||
| 	if cacheSize < 0 { | 	if cacheSize != 0 && cacheSize < minCacheSize { | ||||||
| 		return logical.ErrorResponse("size must be greater or equal to 0"), logical.ErrInvalidRequest | 		return logical.ErrorResponse("size must be 0 or a value greater or equal to %d", minCacheSize), logical.ErrInvalidRequest | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// store cache size | 	// store cache size | ||||||
| @@ -60,11 +59,12 @@ func (b *backend) pathCacheConfigWrite(ctx context.Context, req *logical.Request | |||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	resp := &logical.Response{ | 	err = b.lm.InitCache(cacheSize) | ||||||
| 		Warnings: []string{"cache configurations will be applied when this backend is restarted"}, | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return resp, nil | 	return nil, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| type configCache struct { | type configCache struct { | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| const targetCacheSize = 12345 | const targetCacheSize = 12345 | ||||||
|  | const smallCacheSize = 3 | ||||||
|  |  | ||||||
| func TestTransit_CacheConfig(t *testing.T) { | func TestTransit_CacheConfig(t *testing.T) { | ||||||
| 	b1, storage := createBackendWithSysView(t) | 	b1, storage := createBackendWithSysView(t) | ||||||
| @@ -58,17 +59,51 @@ func TestTransit_CacheConfig(t *testing.T) { | |||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	writeSmallCacheSizeReq := &logical.Request{ | ||||||
|  | 		Storage:   storage, | ||||||
|  | 		Operation: logical.UpdateOperation, | ||||||
|  | 		Path:      "cache-config", | ||||||
|  | 		Data: map[string]interface{}{ | ||||||
|  | 			"size": smallCacheSize, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	readReq := &logical.Request{ | 	readReq := &logical.Request{ | ||||||
| 		Storage:   storage, | 		Storage:   storage, | ||||||
| 		Operation: logical.ReadOperation, | 		Operation: logical.ReadOperation, | ||||||
| 		Path:      "cache-config", | 		Path:      "cache-config", | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	polReq := &logical.Request{ | ||||||
|  | 		Storage:   storage, | ||||||
|  | 		Operation: logical.UpdateOperation, | ||||||
|  | 		Path:      "keys/aes256", | ||||||
|  | 		Data: map[string]interface{}{ | ||||||
|  | 			"derived": true, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
| 	// test steps | 	// test steps | ||||||
| 	// b1 should spin up with an unlimited cache | 	// b1 should spin up with an unlimited cache | ||||||
| 	validateResponse(doReq(b1, readReq), 0, false) | 	validateResponse(doReq(b1, readReq), 0, false) | ||||||
|  |  | ||||||
|  | 	// Change cache size to targetCacheSize 12345 and validate that cache size is updated | ||||||
| 	doReq(b1, writeReq) | 	doReq(b1, writeReq) | ||||||
| 	validateResponse(doReq(b1, readReq), targetCacheSize, true) | 	validateResponse(doReq(b1, readReq), targetCacheSize, false) | ||||||
|  | 	b1.invalidate(context.Background(), "cache-config/") | ||||||
|  |  | ||||||
|  | 	// Change the cache size to 1000 to mock the scenario where | ||||||
|  | 	// current cache size and stored cache size are different and | ||||||
|  | 	// a cache update is needed | ||||||
|  | 	b1.lm.InitCache(1000) | ||||||
|  |  | ||||||
|  | 	// Write a new policy which in its code path detects that cache size has changed | ||||||
|  | 	// and refreshes the cache to 12345 | ||||||
|  | 	doReq(b1, polReq) | ||||||
|  |  | ||||||
|  | 	// Validate that cache size is updated to 12345 | ||||||
|  | 	validateResponse(doReq(b1, readReq), targetCacheSize, false) | ||||||
|  |  | ||||||
| 	// b2 should spin up with a configured cache | 	// b2 should spin up with a configured cache | ||||||
| 	b2 := createBackendWithSysViewWithStorage(t, storage) | 	b2 := createBackendWithSysViewWithStorage(t, storage) | ||||||
| @@ -77,4 +112,10 @@ func TestTransit_CacheConfig(t *testing.T) { | |||||||
| 	// b3 enables transit without a cache, trying to read it should error | 	// b3 enables transit without a cache, trying to read it should error | ||||||
| 	b3 := createBackendWithForceNoCacheWithSysViewWithStorage(t, storage) | 	b3 := createBackendWithForceNoCacheWithSysViewWithStorage(t, storage) | ||||||
| 	doErrReq(b3, readReq) | 	doErrReq(b3, readReq) | ||||||
|  |  | ||||||
|  | 	// b4 should spin up with a size less than minimum cache size (10) | ||||||
|  | 	b4, storage := createBackendWithSysView(t) | ||||||
|  | 	doErrReq(b4, writeSmallCacheSizeReq) | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -62,7 +62,7 @@ func (b *backend) pathConfigWrite(ctx context.Context, req *logical.Request, d * | |||||||
| 	name := d.Get("name").(string) | 	name := d.Get("name").(string) | ||||||
|  |  | ||||||
| 	// Check if the policy already exists before we lock everything | 	// Check if the policy already exists before we lock everything | ||||||
| 	p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{ | 	p, _, err := b.GetPolicy(ctx, keysutil.PolicyRequest{ | ||||||
| 		Storage: req.Storage, | 		Storage: req.Storage, | ||||||
| 		Name:    name, | 		Name:    name, | ||||||
| 	}, b.GetRandomReader()) | 	}, b.GetRandomReader()) | ||||||
|   | |||||||
| @@ -99,7 +99,7 @@ func (b *backend) pathDatakeyWrite(ctx context.Context, req *logical.Request, d | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Get the policy | 	// Get the policy | ||||||
| 	p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{ | 	p, _, err := b.GetPolicy(ctx, keysutil.PolicyRequest{ | ||||||
| 		Storage: req.Storage, | 		Storage: req.Storage, | ||||||
| 		Name:    name, | 		Name:    name, | ||||||
| 	}, b.GetRandomReader()) | 	}, b.GetRandomReader()) | ||||||
|   | |||||||
| @@ -121,7 +121,7 @@ func (b *backend) pathDecryptWrite(ctx context.Context, req *logical.Request, d | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Get the policy | 	// Get the policy | ||||||
| 	p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{ | 	p, _, err := b.GetPolicy(ctx, keysutil.PolicyRequest{ | ||||||
| 		Storage: req.Storage, | 		Storage: req.Storage, | ||||||
| 		Name:    d.Get("name").(string), | 		Name:    d.Get("name").(string), | ||||||
| 	}, b.GetRandomReader()) | 	}, b.GetRandomReader()) | ||||||
|   | |||||||
| @@ -217,7 +217,7 @@ func decodeBatchRequestItems(src interface{}, dst *[]BatchRequestItem) error { | |||||||
|  |  | ||||||
| func (b *backend) pathEncryptExistenceCheck(ctx context.Context, req *logical.Request, d *framework.FieldData) (bool, error) { | func (b *backend) pathEncryptExistenceCheck(ctx context.Context, req *logical.Request, d *framework.FieldData) (bool, error) { | ||||||
| 	name := d.Get("name").(string) | 	name := d.Get("name").(string) | ||||||
| 	p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{ | 	p, _, err := b.GetPolicy(ctx, keysutil.PolicyRequest{ | ||||||
| 		Storage: req.Storage, | 		Storage: req.Storage, | ||||||
| 		Name:    name, | 		Name:    name, | ||||||
| 	}, b.GetRandomReader()) | 	}, b.GetRandomReader()) | ||||||
| @@ -336,7 +336,7 @@ func (b *backend) pathEncryptWrite(ctx context.Context, req *logical.Request, d | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	p, upserted, err = b.lm.GetPolicy(ctx, polReq, b.GetRandomReader()) | 	p, upserted, err = b.GetPolicy(ctx, polReq, b.GetRandomReader()) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -64,7 +64,7 @@ func (b *backend) pathPolicyExportRead(ctx context.Context, req *logical.Request | |||||||
| 		return logical.ErrorResponse(fmt.Sprintf("invalid export type: %s", exportType)), logical.ErrInvalidRequest | 		return logical.ErrorResponse(fmt.Sprintf("invalid export type: %s", exportType)), logical.ErrInvalidRequest | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{ | 	p, _, err := b.GetPolicy(ctx, keysutil.PolicyRequest{ | ||||||
| 		Storage: req.Storage, | 		Storage: req.Storage, | ||||||
| 		Name:    name, | 		Name:    name, | ||||||
| 	}, b.GetRandomReader()) | 	}, b.GetRandomReader()) | ||||||
|   | |||||||
| @@ -96,7 +96,7 @@ func (b *backend) pathHMACWrite(ctx context.Context, req *logical.Request, d *fr | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Get the policy | 	// Get the policy | ||||||
| 	p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{ | 	p, _, err := b.GetPolicy(ctx, keysutil.PolicyRequest{ | ||||||
| 		Storage: req.Storage, | 		Storage: req.Storage, | ||||||
| 		Name:    name, | 		Name:    name, | ||||||
| 	}, b.GetRandomReader()) | 	}, b.GetRandomReader()) | ||||||
| @@ -224,7 +224,7 @@ func (b *backend) pathHMACVerify(ctx context.Context, req *logical.Request, d *f | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Get the policy | 	// Get the policy | ||||||
| 	p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{ | 	p, _, err := b.GetPolicy(ctx, keysutil.PolicyRequest{ | ||||||
| 		Storage: req.Storage, | 		Storage: req.Storage, | ||||||
| 		Name:    name, | 		Name:    name, | ||||||
| 	}, b.GetRandomReader()) | 	}, b.GetRandomReader()) | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ func TestTransit_HMAC(t *testing.T) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Now, change the key value to something we control | 	// Now, change the key value to something we control | ||||||
| 	p, _, err := b.lm.GetPolicy(context.Background(), keysutil.PolicyRequest{ | 	p, _, err := b.GetPolicy(context.Background(), keysutil.PolicyRequest{ | ||||||
| 		Storage: storage, | 		Storage: storage, | ||||||
| 		Name:    "foo", | 		Name:    "foo", | ||||||
| 	}, b.GetRandomReader()) | 	}, b.GetRandomReader()) | ||||||
| @@ -196,7 +196,7 @@ func TestTransit_batchHMAC(t *testing.T) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Now, change the key value to something we control | 	// Now, change the key value to something we control | ||||||
| 	p, _, err := b.lm.GetPolicy(context.Background(), keysutil.PolicyRequest{ | 	p, _, err := b.GetPolicy(context.Background(), keysutil.PolicyRequest{ | ||||||
| 		Storage: storage, | 		Storage: storage, | ||||||
| 		Name:    "foo", | 		Name:    "foo", | ||||||
| 	}, b.GetRandomReader()) | 	}, b.GetRandomReader()) | ||||||
|   | |||||||
| @@ -162,7 +162,7 @@ func (b *backend) pathPolicyWrite(ctx context.Context, req *logical.Request, d * | |||||||
| 		return logical.ErrorResponse(fmt.Sprintf("unknown key type %v", keyType)), logical.ErrInvalidRequest | 		return logical.ErrorResponse(fmt.Sprintf("unknown key type %v", keyType)), logical.ErrInvalidRequest | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	p, upserted, err := b.lm.GetPolicy(ctx, polReq, b.GetRandomReader()) | 	p, upserted, err := b.GetPolicy(ctx, polReq, b.GetRandomReader()) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| @@ -191,7 +191,7 @@ type asymKey struct { | |||||||
| func (b *backend) pathPolicyRead(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { | func (b *backend) pathPolicyRead(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { | ||||||
| 	name := d.Get("name").(string) | 	name := d.Get("name").(string) | ||||||
|  |  | ||||||
| 	p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{ | 	p, _, err := b.GetPolicy(ctx, keysutil.PolicyRequest{ | ||||||
| 		Storage: req.Storage, | 		Storage: req.Storage, | ||||||
| 		Name:    name, | 		Name:    name, | ||||||
| 	}, b.GetRandomReader()) | 	}, b.GetRandomReader()) | ||||||
|   | |||||||
| @@ -114,7 +114,7 @@ func (b *backend) pathRewrapWrite(ctx context.Context, req *logical.Request, d * | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Get the policy | 	// Get the policy | ||||||
| 	p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{ | 	p, _, err := b.GetPolicy(ctx, keysutil.PolicyRequest{ | ||||||
| 		Storage: req.Storage, | 		Storage: req.Storage, | ||||||
| 		Name:    d.Get("name").(string), | 		Name:    d.Get("name").(string), | ||||||
| 	}, b.GetRandomReader()) | 	}, b.GetRandomReader()) | ||||||
|   | |||||||
| @@ -31,7 +31,7 @@ func (b *backend) pathRotateWrite(ctx context.Context, req *logical.Request, d * | |||||||
| 	name := d.Get("name").(string) | 	name := d.Get("name").(string) | ||||||
|  |  | ||||||
| 	// Get the policy | 	// Get the policy | ||||||
| 	p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{ | 	p, _, err := b.GetPolicy(ctx, keysutil.PolicyRequest{ | ||||||
| 		Storage: req.Storage, | 		Storage: req.Storage, | ||||||
| 		Name:    name, | 		Name:    name, | ||||||
| 	}, b.GetRandomReader()) | 	}, b.GetRandomReader()) | ||||||
|   | |||||||
| @@ -246,7 +246,7 @@ func (b *backend) pathSignWrite(ctx context.Context, req *logical.Request, d *fr | |||||||
| 	sigAlgorithm := d.Get("signature_algorithm").(string) | 	sigAlgorithm := d.Get("signature_algorithm").(string) | ||||||
|  |  | ||||||
| 	// Get the policy | 	// Get the policy | ||||||
| 	p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{ | 	p, _, err := b.GetPolicy(ctx, keysutil.PolicyRequest{ | ||||||
| 		Storage: req.Storage, | 		Storage: req.Storage, | ||||||
| 		Name:    name, | 		Name:    name, | ||||||
| 	}, b.GetRandomReader()) | 	}, b.GetRandomReader()) | ||||||
| @@ -464,7 +464,7 @@ func (b *backend) pathVerifyWrite(ctx context.Context, req *logical.Request, d * | |||||||
| 	sigAlgorithm := d.Get("signature_algorithm").(string) | 	sigAlgorithm := d.Get("signature_algorithm").(string) | ||||||
|  |  | ||||||
| 	// Get the policy | 	// Get the policy | ||||||
| 	p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{ | 	p, _, err := b.GetPolicy(ctx, keysutil.PolicyRequest{ | ||||||
| 		Storage: req.Storage, | 		Storage: req.Storage, | ||||||
| 		Name:    name, | 		Name:    name, | ||||||
| 	}, b.GetRandomReader()) | 	}, b.GetRandomReader()) | ||||||
|   | |||||||
| @@ -55,7 +55,7 @@ func testTransit_SignVerify_ECDSA(t *testing.T, bits int) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Now, change the key value to something we control | 	// Now, change the key value to something we control | ||||||
| 	p, _, err := b.lm.GetPolicy(context.Background(), keysutil.PolicyRequest{ | 	p, _, err := b.GetPolicy(context.Background(), keysutil.PolicyRequest{ | ||||||
| 		Storage: storage, | 		Storage: storage, | ||||||
| 		Name:    "foo", | 		Name:    "foo", | ||||||
| 	}, b.GetRandomReader()) | 	}, b.GetRandomReader()) | ||||||
| @@ -377,7 +377,7 @@ func TestTransit_SignVerify_ED25519(t *testing.T) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Get the keys for later | 	// Get the keys for later | ||||||
| 	fooP, _, err := b.lm.GetPolicy(context.Background(), keysutil.PolicyRequest{ | 	fooP, _, err := b.GetPolicy(context.Background(), keysutil.PolicyRequest{ | ||||||
| 		Storage: storage, | 		Storage: storage, | ||||||
| 		Name:    "foo", | 		Name:    "foo", | ||||||
| 	}, b.GetRandomReader()) | 	}, b.GetRandomReader()) | ||||||
| @@ -385,7 +385,7 @@ func TestTransit_SignVerify_ED25519(t *testing.T) { | |||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	barP, _, err := b.lm.GetPolicy(context.Background(), keysutil.PolicyRequest{ | 	barP, _, err := b.GetPolicy(context.Background(), keysutil.PolicyRequest{ | ||||||
| 		Storage: storage, | 		Storage: storage, | ||||||
| 		Name:    "bar", | 		Name:    "bar", | ||||||
| 	}, b.GetRandomReader()) | 	}, b.GetRandomReader()) | ||||||
|   | |||||||
| @@ -40,7 +40,7 @@ func (b *backend) pathTrimUpdate() framework.OperationFunc { | |||||||
| 	return func(ctx context.Context, req *logical.Request, d *framework.FieldData) (resp *logical.Response, retErr error) { | 	return func(ctx context.Context, req *logical.Request, d *framework.FieldData) (resp *logical.Response, retErr error) { | ||||||
| 		name := d.Get("name").(string) | 		name := d.Get("name").(string) | ||||||
|  |  | ||||||
| 		p, _, err := b.lm.GetPolicy(ctx, keysutil.PolicyRequest{ | 		p, _, err := b.GetPolicy(ctx, keysutil.PolicyRequest{ | ||||||
| 			Storage: req.Storage, | 			Storage: req.Storage, | ||||||
| 			Name:    name, | 			Name:    name, | ||||||
| 		}, b.GetRandomReader()) | 		}, b.GetRandomReader()) | ||||||
|   | |||||||
| @@ -36,7 +36,7 @@ func TestTransit_Trim(t *testing.T) { | |||||||
| 	doReq(t, req) | 	doReq(t, req) | ||||||
|  |  | ||||||
| 	// Get the policy and check that the archive has correct number of keys | 	// Get the policy and check that the archive has correct number of keys | ||||||
| 	p, _, err := b.lm.GetPolicy(namespace.RootContext(nil), keysutil.PolicyRequest{ | 	p, _, err := b.GetPolicy(namespace.RootContext(nil), keysutil.PolicyRequest{ | ||||||
| 		Storage: storage, | 		Storage: storage, | ||||||
| 		Name:    "aes", | 		Name:    "aes", | ||||||
| 	}, b.GetRandomReader()) | 	}, b.GetRandomReader()) | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								changelog/12418.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								changelog/12418.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | |||||||
|  | ```release-note:bug | ||||||
|  | Enforce minimum cache size for transit backend. | ||||||
|  | Init cache size on transit backend without restart. | ||||||
|  | ``` | ||||||
| @@ -101,6 +101,24 @@ func (lm *LockManager) InvalidatePolicy(name string) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (lm *LockManager) InitCache(cacheSize int) error { | ||||||
|  | 	if lm.useCache { | ||||||
|  | 		switch { | ||||||
|  | 		case cacheSize < 0: | ||||||
|  | 			return errors.New("cache size must be greater or equal to zero") | ||||||
|  | 		case cacheSize == 0: | ||||||
|  | 			lm.cache = NewTransitSyncMap() | ||||||
|  | 		case cacheSize > 0: | ||||||
|  | 			newLRUCache, err := NewTransitLRU(cacheSize) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return errwrap.Wrapf("failed to create cache: {{err}}", err) | ||||||
|  | 			} | ||||||
|  | 			lm.cache = newLRUCache | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // RestorePolicy acquires an exclusive lock on the policy name and restores the | // RestorePolicy acquires an exclusive lock on the policy name and restores the | ||||||
| // given policy along with the archive. | // given policy along with the archive. | ||||||
| func (lm *LockManager) RestorePolicy(ctx context.Context, storage logical.Storage, name, backup string, force bool) error { | func (lm *LockManager) RestorePolicy(ctx context.Context, storage logical.Storage, name, backup string, force bool) error { | ||||||
|   | |||||||
| @@ -1307,7 +1307,7 @@ using the [`/sys/plugins/reload/backend`][sys-plugin-reload-backend] endpoint. | |||||||
|  |  | ||||||
| - `size` `(int: 0)` - Specifies the size in terms of number of entries. A size of | - `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 |   `0` means unlimited. A _Least Recently Used_ (LRU) caching strategy is used for a | ||||||
|   non-zero cache size. |   non-zero cache size. Must be 0 (default) or a value greater or equal to 10 (minimum cache size). | ||||||
|  |  | ||||||
| ### Sample Payload | ### Sample Payload | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 divyapola5
					divyapola5