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