helper/keysutil: Add a Wrapper object to wrap storage objects (#4147)
This commit is contained in:
parent
fe0a077e17
commit
5e0da6d871
|
@ -52,9 +52,6 @@ var (
|
|||
|
||||
// EncryptedKeyStorageConfig is used to configure an EncryptedKeyStorage object.
|
||||
type EncryptedKeyStorageConfig struct {
|
||||
// Storage is the underlying storage to wrap requests to.
|
||||
Storage logical.Storage
|
||||
|
||||
// Policy is the key policy to use to encrypt the key paths.
|
||||
Policy *Policy
|
||||
|
||||
|
@ -68,9 +65,9 @@ type EncryptedKeyStorageConfig struct {
|
|||
CacheSize int
|
||||
}
|
||||
|
||||
// NewEncryptedKeyStorage takes an EncryptedKeyStorageConfig and returns a new
|
||||
// NewEncryptedKeyStorageWrapper takes an EncryptedKeyStorageConfig and returns a new
|
||||
// EncryptedKeyStorage object.
|
||||
func NewEncryptedKeyStorage(config EncryptedKeyStorageConfig) (*EncryptedKeyStorage, error) {
|
||||
func NewEncryptedKeyStorageWrapper(config EncryptedKeyStorageConfig) (*EncryptedKeyStorageWrapper, error) {
|
||||
if config.Policy == nil {
|
||||
return nil, ErrNilPolicy
|
||||
}
|
||||
|
@ -87,10 +84,6 @@ func NewEncryptedKeyStorage(config EncryptedKeyStorageConfig) (*EncryptedKeyStor
|
|||
return nil, ErrPolicyConvergentVersion
|
||||
}
|
||||
|
||||
if config.Storage == nil {
|
||||
return nil, ErrNilStorage
|
||||
}
|
||||
|
||||
if config.Prefix == "" {
|
||||
config.Prefix = DefaultPrefix
|
||||
}
|
||||
|
@ -109,17 +102,31 @@ func NewEncryptedKeyStorage(config EncryptedKeyStorageConfig) (*EncryptedKeyStor
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &EncryptedKeyStorage{
|
||||
return &EncryptedKeyStorageWrapper{
|
||||
policy: config.Policy,
|
||||
s: config.Storage,
|
||||
prefix: config.Prefix,
|
||||
lru: cache,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type EncryptedKeyStorageWrapper struct {
|
||||
policy *Policy
|
||||
lru *lru.TwoQueueCache
|
||||
prefix string
|
||||
}
|
||||
|
||||
func (f *EncryptedKeyStorageWrapper) Wrap(s logical.Storage) logical.Storage {
|
||||
return &encryptedKeyStorage{
|
||||
policy: f.policy,
|
||||
s: s,
|
||||
prefix: f.prefix,
|
||||
lru: f.lru,
|
||||
}
|
||||
}
|
||||
|
||||
// EncryptedKeyStorage implements the logical.Storage interface and ensures the
|
||||
// storage paths are encrypted in the underlying storage.
|
||||
type EncryptedKeyStorage struct {
|
||||
type encryptedKeyStorage struct {
|
||||
policy *Policy
|
||||
s logical.Storage
|
||||
lru *lru.TwoQueueCache
|
||||
|
@ -130,7 +137,7 @@ type EncryptedKeyStorage struct {
|
|||
// List implements the logical.Storage List method, and decrypts all the items
|
||||
// in a path prefix. This can only operate on full folder structures so the
|
||||
// prefix should end in a "/".
|
||||
func (s *EncryptedKeyStorage) List(ctx context.Context, prefix string) ([]string, error) {
|
||||
func (s *encryptedKeyStorage) List(ctx context.Context, prefix string) ([]string, error) {
|
||||
encPrefix, err := s.encryptPath(prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -200,7 +207,7 @@ func (s *EncryptedKeyStorage) List(ctx context.Context, prefix string) ([]string
|
|||
}
|
||||
|
||||
// Get implements the logical.Storage Get method.
|
||||
func (s *EncryptedKeyStorage) Get(ctx context.Context, path string) (*logical.StorageEntry, error) {
|
||||
func (s *encryptedKeyStorage) Get(ctx context.Context, path string) (*logical.StorageEntry, error) {
|
||||
encPath, err := s.encryptPath(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -210,7 +217,7 @@ func (s *EncryptedKeyStorage) Get(ctx context.Context, path string) (*logical.St
|
|||
}
|
||||
|
||||
// Put implements the logical.Storage Put method.
|
||||
func (s *EncryptedKeyStorage) Put(ctx context.Context, entry *logical.StorageEntry) error {
|
||||
func (s *encryptedKeyStorage) Put(ctx context.Context, entry *logical.StorageEntry) error {
|
||||
encPath, err := s.encryptPath(entry.Key)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -224,7 +231,7 @@ func (s *EncryptedKeyStorage) Put(ctx context.Context, entry *logical.StorageEnt
|
|||
}
|
||||
|
||||
// Delete implements the logical.Storage Delete method.
|
||||
func (s *EncryptedKeyStorage) Delete(ctx context.Context, path string) error {
|
||||
func (s *encryptedKeyStorage) Delete(ctx context.Context, path string) error {
|
||||
encPath, err := s.encryptPath(path)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -236,7 +243,7 @@ func (s *EncryptedKeyStorage) Delete(ctx context.Context, path string) error {
|
|||
// encryptPath takes a plaintext path and encrypts each path section (separated
|
||||
// by "/") with the object's key policy. The context for each encryption is the
|
||||
// plaintext path prefix for the key.
|
||||
func (s *EncryptedKeyStorage) encryptPath(path string) (string, error) {
|
||||
func (s *encryptedKeyStorage) encryptPath(path string) (string, error) {
|
||||
path = paths.Clean(path)
|
||||
|
||||
// Trim the prefix if it starts with a "/"
|
||||
|
|
|
@ -91,7 +91,6 @@ func TestBase58(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestEncrytedKeysStorage_BadPolicy(t *testing.T) {
|
||||
s := &logical.InmemStorage{}
|
||||
policy := &Policy{
|
||||
Name: "metadata",
|
||||
Type: KeyType_AES256_GCM96,
|
||||
|
@ -103,10 +102,9 @@ func TestEncrytedKeysStorage_BadPolicy(t *testing.T) {
|
|||
versionPrefixCache: &sync.Map{},
|
||||
}
|
||||
|
||||
_, err := NewEncryptedKeyStorage(EncryptedKeyStorageConfig{
|
||||
Storage: s,
|
||||
Policy: policy,
|
||||
Prefix: "prefix",
|
||||
_, err := NewEncryptedKeyStorageWrapper(EncryptedKeyStorageConfig{
|
||||
Policy: policy,
|
||||
Prefix: "prefix",
|
||||
})
|
||||
if err != ErrPolicyDerivedKeys {
|
||||
t.Fatalf("Unexpected Error: %s", err)
|
||||
|
@ -123,10 +121,9 @@ func TestEncrytedKeysStorage_BadPolicy(t *testing.T) {
|
|||
versionPrefixCache: &sync.Map{},
|
||||
}
|
||||
|
||||
_, err = NewEncryptedKeyStorage(EncryptedKeyStorageConfig{
|
||||
Storage: s,
|
||||
Policy: policy,
|
||||
Prefix: "prefix",
|
||||
_, err = NewEncryptedKeyStorageWrapper(EncryptedKeyStorageConfig{
|
||||
Policy: policy,
|
||||
Prefix: "prefix",
|
||||
})
|
||||
if err != ErrPolicyConvergentEncryption {
|
||||
t.Fatalf("Unexpected Error: %s", err)
|
||||
|
@ -143,10 +140,9 @@ func TestEncrytedKeysStorage_BadPolicy(t *testing.T) {
|
|||
versionPrefixCache: &sync.Map{},
|
||||
}
|
||||
|
||||
_, err = NewEncryptedKeyStorage(EncryptedKeyStorageConfig{
|
||||
Storage: s,
|
||||
Policy: policy,
|
||||
Prefix: "prefix",
|
||||
_, err = NewEncryptedKeyStorageWrapper(EncryptedKeyStorageConfig{
|
||||
Policy: policy,
|
||||
Prefix: "prefix",
|
||||
})
|
||||
if err != ErrPolicyConvergentVersion {
|
||||
t.Fatalf("Unexpected Error: %s", err)
|
||||
|
@ -162,15 +158,6 @@ func TestEncrytedKeysStorage_BadPolicy(t *testing.T) {
|
|||
VersionTemplate: EncryptedKeyPolicyVersionTpl,
|
||||
versionPrefixCache: &sync.Map{},
|
||||
}
|
||||
|
||||
_, err = NewEncryptedKeyStorage(EncryptedKeyStorageConfig{
|
||||
Storage: nil,
|
||||
Policy: policy,
|
||||
Prefix: "prefix",
|
||||
})
|
||||
if err != ErrNilStorage {
|
||||
t.Fatalf("Unexpected Error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncrytedKeysStorage_CRUD(t *testing.T) {
|
||||
|
@ -193,16 +180,15 @@ func TestEncrytedKeysStorage_CRUD(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
es, err := NewEncryptedKeyStorage(EncryptedKeyStorageConfig{
|
||||
Storage: s,
|
||||
Policy: policy,
|
||||
Prefix: "prefix",
|
||||
es, err := NewEncryptedKeyStorageWrapper(EncryptedKeyStorageConfig{
|
||||
Policy: policy,
|
||||
Prefix: "prefix",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = es.Put(ctx, &logical.StorageEntry{
|
||||
err = es.Wrap(s).Put(ctx, &logical.StorageEntry{
|
||||
Key: "test/foo",
|
||||
Value: []byte("test"),
|
||||
})
|
||||
|
@ -210,7 +196,7 @@ func TestEncrytedKeysStorage_CRUD(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = es.Put(ctx, &logical.StorageEntry{
|
||||
err = es.Wrap(s).Put(ctx, &logical.StorageEntry{
|
||||
Key: "test/foo1/test",
|
||||
Value: []byte("test"),
|
||||
})
|
||||
|
@ -218,13 +204,13 @@ func TestEncrytedKeysStorage_CRUD(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
keys, err := es.List(ctx, "test/")
|
||||
keys, err := es.Wrap(s).List(ctx, "test/")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Test prefixed with "/"
|
||||
keys, err = es.List(ctx, "/test/")
|
||||
keys, err = es.Wrap(s).List(ctx, "/test/")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -234,7 +220,7 @@ func TestEncrytedKeysStorage_CRUD(t *testing.T) {
|
|||
}
|
||||
|
||||
// Test the cached value is correct
|
||||
keys, err = es.List(ctx, "test/")
|
||||
keys, err = es.Wrap(s).List(ctx, "test/")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -243,7 +229,7 @@ func TestEncrytedKeysStorage_CRUD(t *testing.T) {
|
|||
t.Fatalf("bad keys: %#v", keys)
|
||||
}
|
||||
|
||||
data, err := es.Get(ctx, "test/foo")
|
||||
data, err := es.Wrap(s).Get(ctx, "test/foo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -251,12 +237,12 @@ func TestEncrytedKeysStorage_CRUD(t *testing.T) {
|
|||
t.Fatalf("bad data: %#v", data)
|
||||
}
|
||||
|
||||
err = es.Delete(ctx, "test/foo")
|
||||
err = es.Wrap(s).Delete(ctx, "test/foo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data, err = es.Get(ctx, "test/foo")
|
||||
data, err = es.Wrap(s).Get(ctx, "test/foo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -286,17 +272,16 @@ func BenchmarkEncrytedKeyStorage_List(b *testing.B) {
|
|||
b.Fatal(err)
|
||||
}
|
||||
|
||||
es, err := NewEncryptedKeyStorage(EncryptedKeyStorageConfig{
|
||||
Storage: s,
|
||||
Policy: policy,
|
||||
Prefix: "prefix",
|
||||
es, err := NewEncryptedKeyStorageWrapper(EncryptedKeyStorageConfig{
|
||||
Policy: policy,
|
||||
Prefix: "prefix",
|
||||
})
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
for i := 0; i < 10000; i++ {
|
||||
err = es.Put(ctx, &logical.StorageEntry{
|
||||
err = es.Wrap(s).Put(ctx, &logical.StorageEntry{
|
||||
Key: fmt.Sprintf("test/%d", i),
|
||||
Value: []byte("test"),
|
||||
})
|
||||
|
@ -307,7 +292,7 @@ func BenchmarkEncrytedKeyStorage_List(b *testing.B) {
|
|||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
keys, err := es.List(ctx, "test/")
|
||||
keys, err := es.Wrap(s).List(ctx, "test/")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
@ -335,10 +320,9 @@ func BenchmarkEncrytedKeyStorage_Put(b *testing.B) {
|
|||
b.Fatal(err)
|
||||
}
|
||||
|
||||
es, err := NewEncryptedKeyStorage(EncryptedKeyStorageConfig{
|
||||
Storage: s,
|
||||
Policy: policy,
|
||||
Prefix: "prefix",
|
||||
es, err := NewEncryptedKeyStorageWrapper(EncryptedKeyStorageConfig{
|
||||
Policy: policy,
|
||||
Prefix: "prefix",
|
||||
})
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
|
@ -347,7 +331,7 @@ func BenchmarkEncrytedKeyStorage_Put(b *testing.B) {
|
|||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
err = es.Put(ctx, &logical.StorageEntry{
|
||||
err = es.Wrap(s).Put(ctx, &logical.StorageEntry{
|
||||
Key: fmt.Sprintf("test/%d", i),
|
||||
Value: []byte("test"),
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue