1
16
17 package certificate
18
19 import (
20 "bytes"
21 "os"
22 "path/filepath"
23 "testing"
24 )
25
26 func TestUpdateSymlinkExistingFileError(t *testing.T) {
27 dir, err := os.MkdirTemp("", "k8s-test-update-symlink")
28 if err != nil {
29 t.Fatalf("Unable to create the test directory %q: %v", dir, err)
30 }
31 defer func() {
32 if err := os.RemoveAll(dir); err != nil {
33 t.Errorf("Unable to clean up test directory %q: %v", dir, err)
34 }
35 }()
36 pairFile := filepath.Join(dir, "kubelet-current.pem")
37 if err := os.WriteFile(pairFile, nil, 0600); err != nil {
38 t.Fatalf("Unable to create the file %q: %v", pairFile, err)
39 }
40
41 s := fileStore{
42 certDirectory: dir,
43 pairNamePrefix: "kubelet",
44 }
45 if err := s.updateSymlink(pairFile); err == nil {
46 t.Errorf("Got no error, wanted to fail updating the symlink because there is a file there.")
47 }
48 }
49
50 func TestUpdateSymlinkNewFileNotExist(t *testing.T) {
51 dir, err := os.MkdirTemp("", "k8s-test-update-symlink")
52 if err != nil {
53 t.Fatalf("Unable to create the test directory %q: %v", dir, err)
54 }
55 defer func() {
56 if err := os.RemoveAll(dir); err != nil {
57 t.Errorf("Unable to clean up test directory %q: %v", dir, err)
58 }
59 }()
60 oldPairFile := filepath.Join(dir, "kubelet-oldpair.pem")
61 if err := os.WriteFile(oldPairFile, nil, 0600); err != nil {
62 t.Fatalf("Unable to create the file %q: %v", oldPairFile, err)
63 }
64
65 s := fileStore{
66 certDirectory: dir,
67 pairNamePrefix: "kubelet",
68 }
69 if err := s.updateSymlink(oldPairFile); err != nil {
70 t.Errorf("Got error %v, wanted successful update of the symlink to point to %q", err, oldPairFile)
71 }
72
73 if _, err := os.Stat(oldPairFile); err != nil {
74 t.Errorf("Got error %v, wanted file %q to be there.", err, oldPairFile)
75 }
76
77 currentPairFile := filepath.Join(dir, "kubelet-current.pem")
78 if fi, err := os.Lstat(currentPairFile); err != nil {
79 t.Errorf("Got error %v, wanted file %q to be there", err, currentPairFile)
80 } else if fi.Mode()&os.ModeSymlink != os.ModeSymlink {
81 t.Errorf("Got %q not a symlink.", currentPairFile)
82 }
83
84 newPairFile := filepath.Join(dir, "kubelet-newpair.pem")
85 if err := s.updateSymlink(newPairFile); err == nil {
86 t.Errorf("Got no error, wanted to fail updating the symlink the file %q does not exist.", newPairFile)
87 }
88 }
89
90 func TestUpdateSymlinkNoSymlink(t *testing.T) {
91 dir, err := os.MkdirTemp("", "k8s-test-update-symlink")
92 if err != nil {
93 t.Fatalf("Unable to create the test directory %q: %v", dir, err)
94 }
95 defer func() {
96 if err := os.RemoveAll(dir); err != nil {
97 t.Errorf("Unable to clean up test directory %q: %v", dir, err)
98 }
99 }()
100 pairFile := filepath.Join(dir, "kubelet-newfile.pem")
101 if err := os.WriteFile(pairFile, nil, 0600); err != nil {
102 t.Fatalf("Unable to create the file %q: %v", pairFile, err)
103 }
104
105 s := fileStore{
106 certDirectory: dir,
107 pairNamePrefix: "kubelet",
108 }
109 if err := s.updateSymlink(pairFile); err != nil {
110 t.Errorf("Got error %v, wanted a new symlink to be created", err)
111 }
112
113 if _, err := os.Stat(pairFile); err != nil {
114 t.Errorf("Got error %v, wanted file %q to be there", err, pairFile)
115 }
116 currentPairFile := filepath.Join(dir, "kubelet-current.pem")
117 if fi, err := os.Lstat(currentPairFile); err != nil {
118 t.Errorf("Got %v, wanted %q to be there", currentPairFile, err)
119 } else if fi.Mode()&os.ModeSymlink != os.ModeSymlink {
120 t.Errorf("%q not a symlink, wanted a symlink.", currentPairFile)
121 }
122 }
123
124 func TestUpdateSymlinkReplaceExistingSymlink(t *testing.T) {
125 prefix := "kubelet"
126 dir, err := os.MkdirTemp("", "k8s-test-update-symlink")
127 if err != nil {
128 t.Fatalf("Unable to create the test directory %q: %v", dir, err)
129 }
130 defer func() {
131 if err := os.RemoveAll(dir); err != nil {
132 t.Errorf("Unable to clean up test directory %q: %v", dir, err)
133 }
134 }()
135 oldPairFile := filepath.Join(dir, prefix+"-oldfile.pem")
136 if err := os.WriteFile(oldPairFile, nil, 0600); err != nil {
137 t.Fatalf("Unable to create the file %q: %v", oldPairFile, err)
138 }
139 newPairFile := filepath.Join(dir, prefix+"-newfile.pem")
140 if err := os.WriteFile(newPairFile, nil, 0600); err != nil {
141 t.Fatalf("Unable to create the file %q: %v", newPairFile, err)
142 }
143 currentPairFile := filepath.Join(dir, prefix+"-current.pem")
144 if err := os.Symlink(oldPairFile, currentPairFile); err != nil {
145 t.Fatalf("unable to create a symlink from %q to %q: %v", currentPairFile, oldPairFile, err)
146 }
147 if resolved, err := os.Readlink(currentPairFile); err != nil {
148 t.Fatalf("Got %v when attempting to resolve symlink %q", err, currentPairFile)
149 } else if resolved != oldPairFile {
150 t.Fatalf("Got %q as resolution of symlink %q, wanted %q", resolved, currentPairFile, oldPairFile)
151 }
152
153 s := fileStore{
154 certDirectory: dir,
155 pairNamePrefix: prefix,
156 }
157 if err := s.updateSymlink(newPairFile); err != nil {
158 t.Errorf("Got error %v, wanted a new symlink to be created", err)
159 }
160
161 if _, err := os.Stat(oldPairFile); err != nil {
162 t.Errorf("Got error %v, wanted file %q to be there", oldPairFile, err)
163 }
164 if _, err := os.Stat(newPairFile); err != nil {
165 t.Errorf("Got error %v, wanted file %q to be there", newPairFile, err)
166 }
167 if fi, err := os.Lstat(currentPairFile); err != nil {
168 t.Errorf("Got %v, wanted %q to be there", currentPairFile, err)
169 } else if fi.Mode()&os.ModeSymlink != os.ModeSymlink {
170 t.Errorf("%q not a symlink, wanted a symlink.", currentPairFile)
171 }
172 if resolved, err := os.Readlink(currentPairFile); err != nil {
173 t.Fatalf("Got %v when attempting to resolve symlink %q", err, currentPairFile)
174 } else if resolved != newPairFile {
175 t.Fatalf("Got %q as resolution of symlink %q, wanted %q", resolved, currentPairFile, newPairFile)
176 }
177 }
178
179 func TestLoadFile(t *testing.T) {
180 dir, err := os.MkdirTemp("", "k8s-test-load-cert-key-blocks")
181 if err != nil {
182 t.Fatalf("Unable to create the test directory %q: %v", dir, err)
183 }
184 defer func() {
185 if err := os.RemoveAll(dir); err != nil {
186 t.Errorf("Unable to clean up test directory %q: %v", dir, err)
187 }
188 }()
189
190 pairFile := filepath.Join(dir, "kubelet-pair.pem")
191
192 tests := []struct {
193 desc string
194 data []byte
195 }{
196 {desc: "cert and key", data: bytes.Join([][]byte{storeCertData.certificatePEM, storeCertData.keyPEM}, []byte("\n"))},
197 {desc: "key and cert", data: bytes.Join([][]byte{storeCertData.keyPEM, storeCertData.certificatePEM}, []byte("\n"))},
198 }
199 for _, tt := range tests {
200 t.Run(tt.desc, func(t *testing.T) {
201 if err := os.WriteFile(pairFile, tt.data, 0600); err != nil {
202 t.Fatalf("Unable to create the file %q: %v", pairFile, err)
203 }
204 cert, err := loadFile(pairFile)
205 if err != nil {
206 t.Fatalf("Could not load certificate from disk: %v", err)
207 }
208 if cert == nil {
209 t.Fatalf("There was no error, but no certificate data was returned.")
210 }
211 if cert.Leaf == nil {
212 t.Fatalf("Got an empty leaf, expected private data.")
213 }
214 })
215 }
216 }
217
218 func TestUpdateNoRotation(t *testing.T) {
219 prefix := "kubelet-server"
220 dir, err := os.MkdirTemp("", "k8s-test-certstore-current")
221 if err != nil {
222 t.Fatalf("Unable to create the test directory %q: %v", dir, err)
223 }
224 defer func() {
225 if err := os.RemoveAll(dir); err != nil {
226 t.Errorf("Unable to clean up test directory %q: %v", dir, err)
227 }
228 }()
229 keyFile := filepath.Join(dir, "kubelet.key")
230 if err := os.WriteFile(keyFile, storeCertData.keyPEM, 0600); err != nil {
231 t.Fatalf("Unable to create the file %q: %v", keyFile, err)
232 }
233 certFile := filepath.Join(dir, "kubelet.crt")
234 if err := os.WriteFile(certFile, storeCertData.certificatePEM, 0600); err != nil {
235 t.Fatalf("Unable to create the file %q: %v", certFile, err)
236 }
237
238 s, err := NewFileStore(prefix, dir, dir, certFile, keyFile)
239 if err != nil {
240 t.Fatalf("Got %v while creating a new store.", err)
241 }
242
243 cert, err := s.Update(storeCertData.certificatePEM, storeCertData.keyPEM)
244 if err != nil {
245 t.Errorf("Got %v while updating certificate store.", err)
246 }
247 if cert == nil {
248 t.Errorf("Got nil certificate, expected something real.")
249 }
250 }
251
252 func TestUpdateRotation(t *testing.T) {
253 prefix := "kubelet-server"
254 dir, err := os.MkdirTemp("", "k8s-test-certstore-current")
255 if err != nil {
256 t.Fatalf("Unable to create the test directory %q: %v", dir, err)
257 }
258 defer func() {
259 if err := os.RemoveAll(dir); err != nil {
260 t.Errorf("Unable to clean up test directory %q: %v", dir, err)
261 }
262 }()
263 keyFile := filepath.Join(dir, "kubelet.key")
264 if err := os.WriteFile(keyFile, storeCertData.keyPEM, 0600); err != nil {
265 t.Fatalf("Unable to create the file %q: %v", keyFile, err)
266 }
267 certFile := filepath.Join(dir, "kubelet.crt")
268 if err := os.WriteFile(certFile, storeCertData.certificatePEM, 0600); err != nil {
269 t.Fatalf("Unable to create the file %q: %v", certFile, err)
270 }
271
272 s, err := NewFileStore(prefix, dir, dir, certFile, keyFile)
273 if err != nil {
274 t.Fatalf("Got %v while creating a new store.", err)
275 }
276
277 cert, err := s.Update(storeCertData.certificatePEM, storeCertData.keyPEM)
278 if err != nil {
279 t.Fatalf("Got %v while updating certificate store.", err)
280 }
281 if cert == nil {
282 t.Fatalf("Got nil certificate, expected something real.")
283 }
284 }
285
286 func TestUpdateTwoCerts(t *testing.T) {
287 prefix := "kubelet-server"
288 dir, err := os.MkdirTemp("", "k8s-test-certstore-current")
289 if err != nil {
290 t.Fatalf("Unable to create the test directory %q: %v", dir, err)
291 }
292 defer func() {
293 if err := os.RemoveAll(dir); err != nil {
294 t.Errorf("Unable to clean up test directory %q: %v", dir, err)
295 }
296 }()
297 keyFile := filepath.Join(dir, "kubelet.key")
298 if err := os.WriteFile(keyFile, storeTwoCertsData.keyPEM, 0600); err != nil {
299 t.Fatalf("Unable to create the file %q: %v", keyFile, err)
300 }
301 certFile := filepath.Join(dir, "kubelet.crt")
302 if err := os.WriteFile(certFile, storeTwoCertsData.certificatePEM, 0600); err != nil {
303 t.Fatalf("Unable to create the file %q: %v", certFile, err)
304 }
305
306 s, err := NewFileStore(prefix, dir, dir, certFile, keyFile)
307 if err != nil {
308 t.Fatalf("Got %v while creating a new store.", err)
309 }
310
311 cert, err := s.Update(storeTwoCertsData.certificatePEM, storeTwoCertsData.keyPEM)
312 if err != nil {
313 t.Errorf("Got %v while updating certificate store.", err)
314 }
315 if cert == nil {
316 t.Fatalf("Got nil certificate, expected something real.")
317 }
318 if len(cert.Certificate) != 2 {
319 t.Fatalf("Unexpected number of certificates, expected 2, got %v", len(cert.Certificate))
320 }
321 }
322
323 func TestUpdateWithBadCertKeyData(t *testing.T) {
324 prefix := "kubelet-server"
325 dir, err := os.MkdirTemp("", "k8s-test-certstore-current")
326 if err != nil {
327 t.Fatalf("Unable to create the test directory %q: %v", dir, err)
328 }
329 defer func() {
330 if err := os.RemoveAll(dir); err != nil {
331 t.Errorf("Unable to clean up test directory %q: %v", dir, err)
332 }
333 }()
334 keyFile := filepath.Join(dir, "kubelet.key")
335 if err := os.WriteFile(keyFile, storeCertData.keyPEM, 0600); err != nil {
336 t.Fatalf("Unable to create the file %q: %v", keyFile, err)
337 }
338 certFile := filepath.Join(dir, "kubelet.crt")
339 if err := os.WriteFile(certFile, storeCertData.certificatePEM, 0600); err != nil {
340 t.Fatalf("Unable to create the file %q: %v", certFile, err)
341 }
342
343 s, err := NewFileStore(prefix, dir, dir, certFile, keyFile)
344 if err != nil {
345 t.Fatalf("Got %v while creating a new store.", err)
346 }
347
348 cert, err := s.Update([]byte{0, 0}, storeCertData.keyPEM)
349 if err == nil {
350 t.Fatalf("Got no error while updating certificate store with invalid data.")
351 }
352 if cert != nil {
353 t.Fatalf("Got %v certificate returned from the update, expected nil.", cert)
354 }
355 }
356
357 func TestCurrentPairFile(t *testing.T) {
358 prefix := "kubelet-server"
359 dir, err := os.MkdirTemp("", "k8s-test-certstore-current")
360 if err != nil {
361 t.Fatalf("Unable to create the test directory %q: %v", dir, err)
362 }
363 defer func() {
364 if err := os.RemoveAll(dir); err != nil {
365 t.Errorf("Unable to clean up test directory %q: %v", dir, err)
366 }
367 }()
368 pairFile := filepath.Join(dir, prefix+"-pair.pem")
369 data := append(storeCertData.certificatePEM, []byte("\n")...)
370 data = append(data, storeCertData.keyPEM...)
371 if err := os.WriteFile(pairFile, data, 0600); err != nil {
372 t.Fatalf("Unable to create the file %q: %v", pairFile, err)
373 }
374 currentFile := filepath.Join(dir, prefix+"-current.pem")
375 if err := os.Symlink(pairFile, currentFile); err != nil {
376 t.Fatalf("unable to create a symlink from %q to %q: %v", currentFile, pairFile, err)
377 }
378
379 store, err := NewFileStore("kubelet-server", dir, dir, "", "")
380 if err != nil {
381 t.Fatalf("Failed to initialize certificate store: %v", err)
382 }
383
384 cert, err := store.Current()
385 if err != nil {
386 t.Fatalf("Could not load certificate from disk: %v", err)
387 }
388 if cert == nil {
389 t.Fatalf("There was no error, but no certificate data was returned.")
390 }
391 if cert.Leaf == nil {
392 t.Fatalf("Got an empty leaf, expected private data.")
393 }
394 }
395
396 func TestCurrentCertKeyFiles(t *testing.T) {
397 prefix := "kubelet-server"
398 dir, err := os.MkdirTemp("", "k8s-test-certstore-current")
399 if err != nil {
400 t.Fatalf("Unable to create the test directory %q: %v", dir, err)
401 }
402 defer func() {
403 if err := os.RemoveAll(dir); err != nil {
404 t.Errorf("Unable to clean up test directory %q: %v", dir, err)
405 }
406 }()
407 certFile := filepath.Join(dir, "kubelet.crt")
408 if err := os.WriteFile(certFile, storeCertData.certificatePEM, 0600); err != nil {
409 t.Fatalf("Unable to create the file %q: %v", certFile, err)
410 }
411 keyFile := filepath.Join(dir, "kubelet.key")
412 if err := os.WriteFile(keyFile, storeCertData.keyPEM, 0600); err != nil {
413 t.Fatalf("Unable to create the file %q: %v", keyFile, err)
414 }
415
416 store, err := NewFileStore(prefix, dir, dir, certFile, keyFile)
417 if err != nil {
418 t.Fatalf("Failed to initialize certificate store: %v", err)
419 }
420
421 cert, err := store.Current()
422 if err != nil {
423 t.Fatalf("Could not load certificate from disk: %v", err)
424 }
425 if cert == nil {
426 t.Fatalf("There was no error, but no certificate data was returned.")
427 }
428 if cert.Leaf == nil {
429 t.Fatalf("Got an empty leaf, expected private data.")
430 }
431 }
432
433 func TestCurrentTwoCerts(t *testing.T) {
434 prefix := "kubelet-server"
435 dir, err := os.MkdirTemp("", "k8s-test-certstore-current")
436 if err != nil {
437 t.Fatalf("Unable to create the test directory %q: %v", dir, err)
438 }
439 defer func() {
440 if err := os.RemoveAll(dir); err != nil {
441 t.Errorf("Unable to clean up test directory %q: %v", dir, err)
442 }
443 }()
444 certFile := filepath.Join(dir, "kubelet.crt")
445 if err := os.WriteFile(certFile, storeTwoCertsData.certificatePEM, 0600); err != nil {
446 t.Fatalf("Unable to create the file %q: %v", certFile, err)
447 }
448 keyFile := filepath.Join(dir, "kubelet.key")
449 if err := os.WriteFile(keyFile, storeTwoCertsData.keyPEM, 0600); err != nil {
450 t.Fatalf("Unable to create the file %q: %v", keyFile, err)
451 }
452
453 store, err := NewFileStore(prefix, dir, dir, certFile, keyFile)
454 if err != nil {
455 t.Fatalf("Failed to initialize certificate store: %v", err)
456 }
457
458 cert, err := store.Current()
459 if err != nil {
460 t.Fatalf("Could not load certificate from disk: %v", err)
461 }
462 if cert == nil {
463 t.Fatalf("There was no error, but no certificate data was returned.")
464 }
465 if cert.Leaf == nil {
466 t.Fatalf("Got an empty leaf, expected private data.")
467 }
468 if len(cert.Certificate) != 2 {
469 t.Fatalf("Unexpected number of certificates, expected 2, got %v", len(cert.Certificate))
470 }
471 }
472
473 func TestCurrentNoFiles(t *testing.T) {
474 dir, err := os.MkdirTemp("", "k8s-test-certstore-current")
475 if err != nil {
476 t.Fatalf("Unable to create the test directory %q: %v", dir, err)
477 }
478 defer func() {
479 if err := os.RemoveAll(dir); err != nil {
480 t.Errorf("Unable to clean up test directory %q: %v", dir, err)
481 }
482 }()
483
484 store, err := NewFileStore("kubelet-server", dir, dir, "", "")
485 if err != nil {
486 t.Fatalf("Failed to initialize certificate store: %v", err)
487 }
488
489 cert, err := store.Current()
490 if err == nil {
491 t.Fatalf("Got no error, expected an error because the cert/key files don't exist.")
492 }
493 if _, ok := err.(*NoCertKeyError); !ok {
494 t.Fatalf("Got error %v, expected NoCertKeyError.", err)
495 }
496 if cert != nil {
497 t.Fatalf("Got certificate, expected no certificate because the cert/key files don't exist.")
498 }
499 }
500
View as plain text