helper/keysutil: Add a Wrapper object to wrap storage objects (#4147)

This commit is contained in:
Brian Kassouf 2018-03-18 12:59:07 -07:00 committed by GitHub
parent fe0a077e17
commit 5e0da6d871
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 62 deletions

View File

@ -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 "/"

View File

@ -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"),
})