1package keysutil
2
3import (
4	"context"
5	"crypto/rand"
6	"fmt"
7	"reflect"
8	"testing"
9
10	"github.com/hashicorp/vault/sdk/helper/strutil"
11	"github.com/hashicorp/vault/sdk/logical"
12)
13
14var compilerOpt []string
15
16func TestEncrytedKeysStorage_BadPolicy(t *testing.T) {
17	policy := NewPolicy(PolicyConfig{
18		Name:                 "metadata",
19		Type:                 KeyType_AES256_GCM96,
20		Derived:              false,
21		KDF:                  Kdf_hkdf_sha256,
22		ConvergentEncryption: true,
23		VersionTemplate:      EncryptedKeyPolicyVersionTpl,
24	})
25
26	_, err := NewEncryptedKeyStorageWrapper(EncryptedKeyStorageConfig{
27		Policy: policy,
28		Prefix: "prefix",
29	})
30	if err != ErrPolicyDerivedKeys {
31		t.Fatalf("Unexpected Error: %s", err)
32	}
33
34	policy = NewPolicy(PolicyConfig{
35		Name:                 "metadata",
36		Type:                 KeyType_AES256_GCM96,
37		Derived:              true,
38		KDF:                  Kdf_hkdf_sha256,
39		ConvergentEncryption: false,
40		VersionTemplate:      EncryptedKeyPolicyVersionTpl,
41	})
42
43	_, err = NewEncryptedKeyStorageWrapper(EncryptedKeyStorageConfig{
44		Policy: policy,
45		Prefix: "prefix",
46	})
47	if err != ErrPolicyConvergentEncryption {
48		t.Fatalf("Unexpected Error: %s", err)
49	}
50
51	policy = NewPolicy(PolicyConfig{
52		Name:                 "metadata",
53		Type:                 KeyType_AES256_GCM96,
54		Derived:              true,
55		KDF:                  Kdf_hkdf_sha256,
56		ConvergentEncryption: true,
57		VersionTemplate:      EncryptedKeyPolicyVersionTpl,
58	})
59	_, err = NewEncryptedKeyStorageWrapper(EncryptedKeyStorageConfig{
60		Policy: policy,
61		Prefix: "prefix",
62	})
63	if err != nil {
64		t.Fatalf("Unexpected Error: %s", err)
65	}
66}
67
68func TestEncryptedKeysStorage_List(t *testing.T) {
69	s := &logical.InmemStorage{}
70	policy := NewPolicy(PolicyConfig{
71		Name:                 "metadata",
72		Type:                 KeyType_AES256_GCM96,
73		Derived:              true,
74		KDF:                  Kdf_hkdf_sha256,
75		ConvergentEncryption: true,
76		VersionTemplate:      EncryptedKeyPolicyVersionTpl,
77	})
78
79	ctx := context.Background()
80
81	err := policy.Rotate(ctx, s, rand.Reader)
82	if err != nil {
83		t.Fatal(err)
84	}
85
86	es, err := NewEncryptedKeyStorageWrapper(EncryptedKeyStorageConfig{
87		Policy: policy,
88		Prefix: "prefix",
89	})
90	if err != nil {
91		t.Fatal(err)
92	}
93
94	err = es.Wrap(s).Put(ctx, &logical.StorageEntry{
95		Key:   "test",
96		Value: []byte("test"),
97	})
98	if err != nil {
99		t.Fatal(err)
100	}
101
102	err = es.Wrap(s).Put(ctx, &logical.StorageEntry{
103		Key:   "test/foo",
104		Value: []byte("test"),
105	})
106	if err != nil {
107		t.Fatal(err)
108	}
109
110	err = es.Wrap(s).Put(ctx, &logical.StorageEntry{
111		Key:   "test/foo1/test",
112		Value: []byte("test"),
113	})
114	if err != nil {
115		t.Fatal(err)
116	}
117
118	keys, err := es.Wrap(s).List(ctx, "test/")
119	if err != nil {
120		t.Fatal(err)
121	}
122
123	// Test prefixed with "/"
124	keys, err = es.Wrap(s).List(ctx, "/test/")
125	if err != nil {
126		t.Fatal(err)
127	}
128
129	if len(keys) != 2 || keys[1] != "foo1/" || keys[0] != "foo" {
130		t.Fatalf("bad keys: %#v", keys)
131	}
132
133	keys, err = es.Wrap(s).List(ctx, "/")
134	if err != nil {
135		t.Fatal(err)
136	}
137	if len(keys) != 2 || keys[0] != "test" || keys[1] != "test/" {
138		t.Fatalf("bad keys: %#v", keys)
139	}
140
141	keys, err = es.Wrap(s).List(ctx, "")
142	if err != nil {
143		t.Fatal(err)
144	}
145	if len(keys) != 2 || keys[0] != "test" || keys[1] != "test/" {
146		t.Fatalf("bad keys: %#v", keys)
147	}
148}
149
150func TestEncryptedKeysStorage_CRUD(t *testing.T) {
151	s := &logical.InmemStorage{}
152	policy := NewPolicy(PolicyConfig{
153		Name:                 "metadata",
154		Type:                 KeyType_AES256_GCM96,
155		Derived:              true,
156		KDF:                  Kdf_hkdf_sha256,
157		ConvergentEncryption: true,
158		VersionTemplate:      EncryptedKeyPolicyVersionTpl,
159	})
160
161	ctx := context.Background()
162
163	err := policy.Rotate(ctx, s, rand.Reader)
164	if err != nil {
165		t.Fatal(err)
166	}
167
168	es, err := NewEncryptedKeyStorageWrapper(EncryptedKeyStorageConfig{
169		Policy: policy,
170		Prefix: "prefix",
171	})
172	if err != nil {
173		t.Fatal(err)
174	}
175
176	err = es.Wrap(s).Put(ctx, &logical.StorageEntry{
177		Key:   "test/foo",
178		Value: []byte("test"),
179	})
180	if err != nil {
181		t.Fatal(err)
182	}
183
184	err = es.Wrap(s).Put(ctx, &logical.StorageEntry{
185		Key:   "test/foo1/test",
186		Value: []byte("test"),
187	})
188	if err != nil {
189		t.Fatal(err)
190	}
191
192	keys, err := es.Wrap(s).List(ctx, "test/")
193	if err != nil {
194		t.Fatal(err)
195	}
196
197	// Test prefixed with "/"
198	keys, err = es.Wrap(s).List(ctx, "/test/")
199	if err != nil {
200		t.Fatal(err)
201	}
202
203	if len(keys) != 2 || !strutil.StrListContains(keys, "foo1/") || !strutil.StrListContains(keys, "foo") {
204		t.Fatalf("bad keys: %#v", keys)
205	}
206
207	// Test the cached value is correct
208	keys, err = es.Wrap(s).List(ctx, "test/")
209	if err != nil {
210		t.Fatal(err)
211	}
212
213	if len(keys) != 2 || !strutil.StrListContains(keys, "foo1/") || !strutil.StrListContains(keys, "foo") {
214		t.Fatalf("bad keys: %#v", keys)
215	}
216
217	data, err := es.Wrap(s).Get(ctx, "test/foo")
218	if err != nil {
219		t.Fatal(err)
220	}
221	if !reflect.DeepEqual(data.Value, []byte("test")) {
222		t.Fatalf("bad data: %#v", data)
223	}
224
225	err = es.Wrap(s).Delete(ctx, "test/foo")
226	if err != nil {
227		t.Fatal(err)
228	}
229
230	data, err = es.Wrap(s).Get(ctx, "test/foo")
231	if err != nil {
232		t.Fatal(err)
233	}
234	if data != nil {
235		t.Fatal("data should be nil")
236	}
237
238}
239
240func BenchmarkEncrytedKeyStorage_List(b *testing.B) {
241	s := &logical.InmemStorage{}
242	policy := NewPolicy(PolicyConfig{
243		Name:                 "metadata",
244		Type:                 KeyType_AES256_GCM96,
245		Derived:              true,
246		KDF:                  Kdf_hkdf_sha256,
247		ConvergentEncryption: true,
248		VersionTemplate:      EncryptedKeyPolicyVersionTpl,
249	})
250
251	ctx := context.Background()
252
253	err := policy.Rotate(ctx, s, rand.Reader)
254	if err != nil {
255		b.Fatal(err)
256	}
257
258	es, err := NewEncryptedKeyStorageWrapper(EncryptedKeyStorageConfig{
259		Policy: policy,
260		Prefix: "prefix",
261	})
262	if err != nil {
263		b.Fatal(err)
264	}
265
266	for i := 0; i < 10000; i++ {
267		err = es.Wrap(s).Put(ctx, &logical.StorageEntry{
268			Key:   fmt.Sprintf("test/%d", i),
269			Value: []byte("test"),
270		})
271		if err != nil {
272			b.Fatal(err)
273		}
274	}
275	b.ResetTimer()
276
277	for i := 0; i < b.N; i++ {
278		keys, err := es.Wrap(s).List(ctx, "test/")
279		if err != nil {
280			b.Fatal(err)
281		}
282		compilerOpt = keys
283	}
284}
285
286func BenchmarkEncrytedKeyStorage_Put(b *testing.B) {
287	s := &logical.InmemStorage{}
288	policy := NewPolicy(PolicyConfig{
289		Name:                 "metadata",
290		Type:                 KeyType_AES256_GCM96,
291		Derived:              true,
292		KDF:                  Kdf_hkdf_sha256,
293		ConvergentEncryption: true,
294		VersionTemplate:      EncryptedKeyPolicyVersionTpl,
295	})
296
297	ctx := context.Background()
298
299	err := policy.Rotate(ctx, s, rand.Reader)
300	if err != nil {
301		b.Fatal(err)
302	}
303
304	es, err := NewEncryptedKeyStorageWrapper(EncryptedKeyStorageConfig{
305		Policy: policy,
306		Prefix: "prefix",
307	})
308	if err != nil {
309		b.Fatal(err)
310	}
311
312	b.ResetTimer()
313
314	for i := 0; i < b.N; i++ {
315		err = es.Wrap(s).Put(ctx, &logical.StorageEntry{
316			Key:   fmt.Sprintf("test/%d", i),
317			Value: []byte("test"),
318		})
319		if err != nil {
320			b.Fatal(err)
321		}
322	}
323}
324