1
16
17 package pkiutil
18
19 import (
20 "crypto"
21 "crypto/ecdsa"
22 "crypto/elliptic"
23 "crypto/rand"
24 "crypto/x509"
25 "fmt"
26 "net"
27 "os"
28 "path/filepath"
29 "reflect"
30 "testing"
31
32 certutil "k8s.io/client-go/util/cert"
33 netutils "k8s.io/utils/net"
34
35 kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
36 )
37
38 var (
39
40
41
42 rootCACert, servCert *x509.Certificate
43 rootCAKey, servKey crypto.Signer
44
45 ecdsaKey *ecdsa.PrivateKey
46 )
47
48 func TestMain(m *testing.M) {
49 var err error
50
51 rootCACert, rootCAKey, err = NewCertificateAuthority(&CertConfig{
52 Config: certutil.Config{
53 CommonName: "Root CA 1",
54 },
55 EncryptionAlgorithm: kubeadmapi.EncryptionAlgorithmRSA2048,
56 })
57 if err != nil {
58 panic(fmt.Sprintf("Failed generating Root CA: %v", err))
59 }
60 if !rootCACert.IsCA {
61 panic("rootCACert is not a valid CA")
62 }
63
64 servCert, servKey, err = NewCertAndKey(rootCACert, rootCAKey, &CertConfig{
65 Config: certutil.Config{
66 CommonName: "kubernetes",
67 Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
68 },
69 })
70 if err != nil {
71 panic(fmt.Sprintf("Failed generating serving cert/key: %v", err))
72 }
73
74 ecdsaKey, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
75 if err != nil {
76 panic("Could not generate ECDSA key")
77 }
78
79 os.Exit(m.Run())
80 }
81
82 func TestNewCertAndKey(t *testing.T) {
83 var tests = []struct {
84 name string
85 key crypto.Signer
86 }{
87 {
88 name: "ECDSA should succeed",
89 key: ecdsaKey,
90 },
91 }
92
93 for _, rt := range tests {
94 t.Run(rt.name, func(t *testing.T) {
95 caCert := &x509.Certificate{}
96 config := &CertConfig{
97 Config: certutil.Config{
98 CommonName: "test",
99 Organization: []string{"test"},
100 Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
101 },
102 }
103 _, _, err := NewCertAndKey(caCert, rt.key, config)
104 if err != nil {
105 t.Errorf("failed NewCertAndKey: %v", err)
106 }
107 })
108 }
109 }
110
111 func TestHasServerAuth(t *testing.T) {
112
113
114 privateKeyFunc := NewPrivateKey
115 NewPrivateKey = func(kubeadmapi.EncryptionAlgorithmType) (crypto.Signer, error) {
116 return rootCAKey, nil
117 }
118 defer func() {
119 NewPrivateKey = privateKeyFunc
120 }()
121
122 var tests = []struct {
123 name string
124 config CertConfig
125 expected bool
126 }{
127 {
128 name: "has ServerAuth",
129 config: CertConfig{
130 Config: certutil.Config{
131 CommonName: "test",
132 Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
133 },
134 },
135 expected: true,
136 },
137 {
138 name: "has ServerAuth ECDSA",
139 config: CertConfig{
140 Config: certutil.Config{
141 CommonName: "test",
142 Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
143 },
144 EncryptionAlgorithm: kubeadmapi.EncryptionAlgorithmECDSAP256,
145 },
146 expected: true,
147 },
148 {
149 name: "doesn't have ServerAuth",
150 config: CertConfig{
151 Config: certutil.Config{
152 CommonName: "test",
153 Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
154 },
155 },
156 expected: false,
157 },
158 }
159
160 for _, rt := range tests {
161 t.Run(rt.name, func(t *testing.T) {
162 cert, _, err := NewCertAndKey(rootCACert, rootCAKey, &rt.config)
163 if err != nil {
164 t.Fatalf("Couldn't create cert: %v", err)
165 }
166 actual := HasServerAuth(cert)
167 if actual != rt.expected {
168 t.Errorf(
169 "failed HasServerAuth:\n\texpected: %t\n\t actual: %t",
170 rt.expected,
171 actual,
172 )
173 }
174 })
175 }
176 }
177
178 func TestWriteCertAndKey(t *testing.T) {
179 tmpdir, err := os.MkdirTemp("", "")
180 if err != nil {
181 t.Fatalf("Couldn't create tmpdir")
182 }
183 defer os.RemoveAll(tmpdir)
184
185 caCert := &x509.Certificate{}
186 actual := WriteCertAndKey(tmpdir, "foo", caCert, rootCAKey)
187 if actual != nil {
188 t.Errorf(
189 "failed WriteCertAndKey with an error: %v",
190 actual,
191 )
192 }
193 }
194
195 func TestWriteCert(t *testing.T) {
196 tmpdir, err := os.MkdirTemp("", "")
197 if err != nil {
198 t.Fatalf("Couldn't create tmpdir")
199 }
200 defer os.RemoveAll(tmpdir)
201
202 caCert := &x509.Certificate{}
203 actual := WriteCert(tmpdir, "foo", caCert)
204 if actual != nil {
205 t.Errorf(
206 "failed WriteCert with an error: %v",
207 actual,
208 )
209 }
210 }
211
212 func TestWriteCertBundle(t *testing.T) {
213 tmpdir, err := os.MkdirTemp("", "")
214 if err != nil {
215 t.Fatalf("Couldn't create tmpdir")
216 }
217 defer os.RemoveAll(tmpdir)
218
219 certs := []*x509.Certificate{{}, {}}
220
221 actual := WriteCertBundle(tmpdir, "foo", certs)
222 if actual != nil {
223 t.Errorf("failed WriteCertBundle with an error: %v", actual)
224 }
225 }
226
227 func TestWriteKey(t *testing.T) {
228 tmpdir, err := os.MkdirTemp("", "")
229 if err != nil {
230 t.Fatalf("Couldn't create tmpdir")
231 }
232 defer os.RemoveAll(tmpdir)
233
234 actual := WriteKey(tmpdir, "foo", rootCAKey)
235 if actual != nil {
236 t.Errorf(
237 "failed WriteCertAndKey with an error: %v",
238 actual,
239 )
240 }
241 }
242
243 func TestWritePublicKey(t *testing.T) {
244 tmpdir, err := os.MkdirTemp("", "")
245 if err != nil {
246 t.Fatalf("Couldn't create tmpdir")
247 }
248 defer os.RemoveAll(tmpdir)
249
250 actual := WritePublicKey(tmpdir, "foo", rootCAKey.Public())
251 if actual != nil {
252 t.Errorf(
253 "failed WriteCertAndKey with an error: %v",
254 actual,
255 )
256 }
257 }
258
259 func TestCertOrKeyExist(t *testing.T) {
260 tmpdir, err := os.MkdirTemp("", "")
261 if err != nil {
262 t.Fatalf("Couldn't create tmpdir")
263 }
264 defer os.RemoveAll(tmpdir)
265
266 if err = WriteCertAndKey(tmpdir, "foo-0", rootCACert, rootCAKey); err != nil {
267 t.Errorf(
268 "failed WriteCertAndKey with an error: %v",
269 err,
270 )
271 }
272 if err = WriteCert(tmpdir, "foo-1", rootCACert); err != nil {
273 t.Errorf(
274 "failed WriteCert with an error: %v",
275 err,
276 )
277 }
278
279 var tests = []struct {
280 desc string
281 path string
282 name string
283 expected bool
284 }{
285 {
286 desc: "empty path and name",
287 path: "",
288 name: "",
289 expected: false,
290 },
291 {
292 desc: "valid path and name, both cert and key exist",
293 path: tmpdir,
294 name: "foo-0",
295 expected: true,
296 },
297 {
298 desc: "valid path and name, only cert exist",
299 path: tmpdir,
300 name: "foo-1",
301 expected: true,
302 },
303 }
304 for _, rt := range tests {
305 t.Run(rt.name, func(t *testing.T) {
306 actual := CertOrKeyExist(rt.path, rt.name)
307 if actual != rt.expected {
308 t.Errorf(
309 "failed CertOrKeyExist:\n\texpected: %t\n\t actual: %t",
310 rt.expected,
311 actual,
312 )
313 }
314 })
315 }
316 }
317
318 func TestTryLoadCertAndKeyFromDisk(t *testing.T) {
319 tmpdir, err := os.MkdirTemp("", "")
320 if err != nil {
321 t.Fatalf("Couldn't create tmpdir")
322 }
323 defer os.RemoveAll(tmpdir)
324
325 err = WriteCertAndKey(tmpdir, "foo", rootCACert, rootCAKey)
326 if err != nil {
327 t.Fatalf(
328 "failed to write cert and key with an error: %v",
329 err,
330 )
331 }
332
333 var tests = []struct {
334 desc string
335 path string
336 name string
337 expected bool
338 }{
339 {
340 desc: "empty path and name",
341 path: "",
342 name: "",
343 expected: false,
344 },
345 {
346 desc: "valid path and name",
347 path: tmpdir,
348 name: "foo",
349 expected: true,
350 },
351 }
352 for _, rt := range tests {
353 t.Run(rt.desc, func(t *testing.T) {
354 _, _, actual := TryLoadCertAndKeyFromDisk(rt.path, rt.name)
355 if (actual == nil) != rt.expected {
356 t.Errorf(
357 "failed TryLoadCertAndKeyFromDisk:\n\texpected: %t\n\t actual: %t",
358 rt.expected,
359 (actual == nil),
360 )
361 }
362 })
363 }
364 }
365
366 func TestTryLoadCertFromDisk(t *testing.T) {
367 tmpdir, err := os.MkdirTemp("", "")
368 if err != nil {
369 t.Fatalf("Couldn't create tmpdir")
370 }
371 defer os.RemoveAll(tmpdir)
372
373 err = WriteCert(tmpdir, "foo", rootCACert)
374 if err != nil {
375 t.Fatalf(
376 "failed to write cert and key with an error: %v",
377 err,
378 )
379 }
380
381 var tests = []struct {
382 desc string
383 path string
384 name string
385 expected bool
386 }{
387 {
388 desc: "empty path and name",
389 path: "",
390 name: "",
391 expected: false,
392 },
393 {
394 desc: "valid path and name",
395 path: tmpdir,
396 name: "foo",
397 expected: true,
398 },
399 }
400 for _, rt := range tests {
401 t.Run(rt.desc, func(t *testing.T) {
402 _, actual := TryLoadCertFromDisk(rt.path, rt.name)
403 if (actual == nil) != rt.expected {
404 t.Errorf(
405 "failed TryLoadCertAndKeyFromDisk:\n\texpected: %t\n\t actual: %t",
406 rt.expected,
407 (actual == nil),
408 )
409 }
410 })
411 }
412 }
413
414 func TestTryLoadCertChainFromDisk(t *testing.T) {
415 tmpdir, err := os.MkdirTemp("", "")
416 if err != nil {
417 t.Fatalf("Couldn't create tmpdir")
418 }
419 defer os.RemoveAll(tmpdir)
420
421 err = WriteCert(tmpdir, "leaf", servCert)
422 if err != nil {
423 t.Fatalf("failed to write cert: %v", err)
424 }
425
426
427 bundle := []*x509.Certificate{servCert, rootCACert}
428 err = WriteCertBundle(tmpdir, "bundle", bundle)
429 if err != nil {
430 t.Fatalf("failed to write cert bundle: %v", err)
431 }
432
433 var tests = []struct {
434 desc string
435 path string
436 name string
437 expected bool
438 intermediates int
439 }{
440 {
441 desc: "empty path and name",
442 path: "",
443 name: "",
444 expected: false,
445 intermediates: 0,
446 },
447 {
448 desc: "leaf certificate",
449 path: tmpdir,
450 name: "leaf",
451 expected: true,
452 intermediates: 0,
453 },
454 {
455 desc: "certificate bundle",
456 path: tmpdir,
457 name: "bundle",
458 expected: true,
459 intermediates: 1,
460 },
461 }
462 for _, rt := range tests {
463 t.Run(rt.desc, func(t *testing.T) {
464 _, intermediates, actual := TryLoadCertChainFromDisk(rt.path, rt.name)
465 if (actual == nil) != rt.expected {
466 t.Errorf(
467 "failed TryLoadCertChainFromDisk:\n\texpected: %t\n\t actual: %t",
468 rt.expected,
469 (actual == nil),
470 )
471 }
472 if len(intermediates) != rt.intermediates {
473 t.Errorf(
474 "TryLoadCertChainFromDisk returned the wrong number of intermediate certificates:\n\texpected: %d\n\t actual: %d",
475 rt.intermediates,
476 len(intermediates),
477 )
478 }
479 })
480 }
481 }
482
483 func TestTryLoadKeyFromDisk(t *testing.T) {
484 var tests = []struct {
485 desc string
486 pathSuffix string
487 name string
488 caKey crypto.Signer
489 expected bool
490 }{
491 {
492 desc: "empty path and name",
493 pathSuffix: "somegarbage",
494 name: "",
495 caKey: rootCAKey,
496 expected: false,
497 },
498 {
499 desc: "RSA valid path and name",
500 pathSuffix: "",
501 name: "foo",
502 caKey: rootCAKey,
503 expected: true,
504 },
505 {
506 desc: "ECDSA valid path and name",
507 pathSuffix: "",
508 name: "foo",
509 caKey: ecdsaKey,
510 expected: true,
511 },
512 }
513 for _, rt := range tests {
514 t.Run(rt.desc, func(t *testing.T) {
515 tmpdir, err := os.MkdirTemp("", "")
516 if err != nil {
517 t.Fatalf("Couldn't create tmpdir")
518 }
519 defer os.RemoveAll(tmpdir)
520
521 err = WriteKey(tmpdir, "foo", rt.caKey)
522 if err != nil {
523 t.Errorf(
524 "failed to write key with an error: %v",
525 err,
526 )
527 }
528 _, actual := TryLoadKeyFromDisk(tmpdir+rt.pathSuffix, rt.name)
529 if (actual == nil) != rt.expected {
530 t.Errorf(
531 "failed TryLoadCertAndKeyFromDisk:\n\texpected: %t\n\t actual: %t",
532 rt.expected,
533 (actual == nil),
534 )
535 }
536 })
537 }
538 }
539
540 func TestPathsForCertAndKey(t *testing.T) {
541 crtPath, keyPath := PathsForCertAndKey("/foo", "bar")
542 expectedPath := filepath.FromSlash("/foo/bar.crt")
543 if crtPath != expectedPath {
544 t.Errorf("unexpected certificate path: %s", crtPath)
545 }
546 expectedPath = filepath.FromSlash("/foo/bar.key")
547 if keyPath != expectedPath {
548 t.Errorf("unexpected key path: %s", keyPath)
549 }
550 }
551
552 func TestPathForCert(t *testing.T) {
553 crtPath := pathForCert("/foo", "bar")
554 expectedPath := filepath.FromSlash("/foo/bar.crt")
555 if crtPath != expectedPath {
556 t.Errorf("unexpected certificate path: %s", crtPath)
557 }
558 }
559
560 func TestPathForKey(t *testing.T) {
561 keyPath := pathForKey("/foo", "bar")
562 expectedPath := filepath.FromSlash("/foo/bar.key")
563 if keyPath != expectedPath {
564 t.Errorf("unexpected certificate path: %s", keyPath)
565 }
566 }
567
568 func TestPathForPublicKey(t *testing.T) {
569 pubPath := pathForPublicKey("/foo", "bar")
570 expectedPath := filepath.FromSlash("/foo/bar.pub")
571 if pubPath != expectedPath {
572 t.Errorf("unexpected certificate path: %s", pubPath)
573 }
574 }
575
576 func TestPathForCSR(t *testing.T) {
577 csrPath := pathForCSR("/foo", "bar")
578 expectedPath := filepath.FromSlash("/foo/bar.csr")
579 if csrPath != expectedPath {
580 t.Errorf("unexpected certificate path: %s", csrPath)
581 }
582 }
583
584 func TestGetAPIServerAltNames(t *testing.T) {
585
586 var tests = []struct {
587 desc string
588 name string
589 cfg *kubeadmapi.InitConfiguration
590 expectedDNSNames []string
591 expectedIPAddresses []string
592 }{
593 {
594 desc: "empty name",
595 name: "",
596 cfg: &kubeadmapi.InitConfiguration{
597 LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "1.2.3.4"},
598 ClusterConfiguration: kubeadmapi.ClusterConfiguration{
599 ControlPlaneEndpoint: "api.k8s.io:6443",
600 Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"},
601 APIServer: kubeadmapi.APIServer{
602 CertSANs: []string{"10.1.245.94", "10.1.245.95", "1.2.3.L", "invalid,commas,in,DNS"},
603 },
604 },
605 NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"},
606 },
607 expectedDNSNames: []string{"valid-hostname", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster.local", "api.k8s.io"},
608 expectedIPAddresses: []string{"10.96.0.1", "1.2.3.4", "10.1.245.94", "10.1.245.95"},
609 },
610 {
611 desc: "ControlPlaneEndpoint IP",
612 name: "ControlPlaneEndpoint IP",
613 cfg: &kubeadmapi.InitConfiguration{
614 LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "1.2.3.4"},
615 ClusterConfiguration: kubeadmapi.ClusterConfiguration{
616 ControlPlaneEndpoint: "4.5.6.7:6443",
617 Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"},
618 APIServer: kubeadmapi.APIServer{
619 CertSANs: []string{"10.1.245.94", "10.1.245.95", "1.2.3.L", "invalid,commas,in,DNS"},
620 },
621 },
622 NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-hostname"},
623 },
624 expectedDNSNames: []string{"valid-hostname", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster.local"},
625 expectedIPAddresses: []string{"10.96.0.1", "1.2.3.4", "10.1.245.94", "10.1.245.95", "4.5.6.7"},
626 },
627 }
628
629 for _, rt := range tests {
630 t.Run(rt.desc, func(t *testing.T) {
631 altNames, err := GetAPIServerAltNames(rt.cfg)
632 if err != nil {
633 t.Fatalf("failed calling GetAPIServerAltNames: %s: %v", rt.name, err)
634 }
635
636 for _, DNSName := range rt.expectedDNSNames {
637 found := false
638 for _, val := range altNames.DNSNames {
639 if val == DNSName {
640 found = true
641 break
642 }
643 }
644
645 if !found {
646 t.Errorf("%s: altNames does not contain DNSName %s but %v", rt.name, DNSName, altNames.DNSNames)
647 }
648 }
649
650 for _, IPAddress := range rt.expectedIPAddresses {
651 found := false
652 for _, val := range altNames.IPs {
653 if val.Equal(netutils.ParseIPSloppy(IPAddress)) {
654 found = true
655 break
656 }
657 }
658
659 if !found {
660 t.Errorf("%s: altNames does not contain IPAddress %s but %v", rt.name, IPAddress, altNames.IPs)
661 }
662 }
663 })
664 }
665 }
666
667 func TestGetEtcdAltNames(t *testing.T) {
668 proxy := "user-etcd-proxy"
669 proxyIP := "10.10.10.100"
670 cfg := &kubeadmapi.InitConfiguration{
671 LocalAPIEndpoint: kubeadmapi.APIEndpoint{
672 AdvertiseAddress: "1.2.3.4",
673 },
674 NodeRegistration: kubeadmapi.NodeRegistrationOptions{
675 Name: "myNode",
676 },
677 ClusterConfiguration: kubeadmapi.ClusterConfiguration{
678 Etcd: kubeadmapi.Etcd{
679 Local: &kubeadmapi.LocalEtcd{
680 ServerCertSANs: []string{
681 proxy,
682 proxyIP,
683 "1.2.3.L",
684 "invalid,commas,in,DNS",
685 },
686 },
687 },
688 },
689 }
690
691 altNames, err := GetEtcdAltNames(cfg)
692 if err != nil {
693 t.Fatalf("failed calling GetEtcdAltNames: %v", err)
694 }
695
696 expectedDNSNames := []string{"myNode", "localhost", proxy}
697 for _, DNSName := range expectedDNSNames {
698 t.Run(DNSName, func(t *testing.T) {
699 found := false
700 for _, val := range altNames.DNSNames {
701 if val == DNSName {
702 found = true
703 break
704 }
705 }
706
707 if !found {
708 t.Errorf("altNames does not contain DNSName %s", DNSName)
709 }
710 })
711 }
712
713 expectedIPAddresses := []string{"1.2.3.4", "127.0.0.1", net.IPv6loopback.String(), proxyIP}
714 for _, IPAddress := range expectedIPAddresses {
715 t.Run(IPAddress, func(t *testing.T) {
716 found := false
717 for _, val := range altNames.IPs {
718 if val.Equal(netutils.ParseIPSloppy(IPAddress)) {
719 found = true
720 break
721 }
722 }
723
724 if !found {
725 t.Errorf("altNames does not contain IPAddress %s", IPAddress)
726 }
727 })
728 }
729 }
730
731 func TestGetEtcdPeerAltNames(t *testing.T) {
732 hostname := "valid-hostname"
733 proxy := "user-etcd-proxy"
734 proxyIP := "10.10.10.100"
735 advertiseIP := "1.2.3.4"
736 cfg := &kubeadmapi.InitConfiguration{
737 LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: advertiseIP},
738 ClusterConfiguration: kubeadmapi.ClusterConfiguration{
739 Etcd: kubeadmapi.Etcd{
740 Local: &kubeadmapi.LocalEtcd{
741 PeerCertSANs: []string{
742 proxy,
743 proxyIP,
744 "1.2.3.L",
745 "invalid,commas,in,DNS",
746 },
747 },
748 },
749 },
750 NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: hostname},
751 }
752
753 altNames, err := GetEtcdPeerAltNames(cfg)
754 if err != nil {
755 t.Fatalf("failed calling GetEtcdPeerAltNames: %v", err)
756 }
757
758 expectedDNSNames := []string{hostname, proxy}
759 for _, DNSName := range expectedDNSNames {
760 t.Run(DNSName, func(t *testing.T) {
761 found := false
762 for _, val := range altNames.DNSNames {
763 if val == DNSName {
764 found = true
765 break
766 }
767 }
768
769 if !found {
770 t.Errorf("altNames does not contain DNSName %s", DNSName)
771 }
772
773 expectedIPAddresses := []string{advertiseIP, proxyIP}
774 for _, IPAddress := range expectedIPAddresses {
775 found := false
776 for _, val := range altNames.IPs {
777 if val.Equal(netutils.ParseIPSloppy(IPAddress)) {
778 found = true
779 break
780 }
781 }
782
783 if !found {
784 t.Errorf("altNames does not contain IPAddress %s", IPAddress)
785 }
786 }
787 })
788 }
789 }
790
791 func TestAppendSANsToAltNames(t *testing.T) {
792 var tests = []struct {
793 sans []string
794 expected int
795 }{
796 {[]string{}, 0},
797 {[]string{"abc"}, 1},
798 {[]string{"*.abc"}, 1},
799 {[]string{"**.abc"}, 0},
800 {[]string{"a.*.bc"}, 0},
801 {[]string{"a.*.bc", "abc.def"}, 1},
802 {[]string{"a*.bc", "abc.def"}, 1},
803 }
804 for _, rt := range tests {
805 altNames := certutil.AltNames{}
806 appendSANsToAltNames(&altNames, rt.sans, "foo")
807 actual := len(altNames.DNSNames)
808 if actual != rt.expected {
809 t.Errorf(
810 "failed AppendSANsToAltNames Numbers:\n\texpected: %d\n\t actual: %d",
811 rt.expected,
812 actual,
813 )
814 }
815 }
816
817 }
818
819 func TestRemoveDuplicateAltNames(t *testing.T) {
820 tests := []struct {
821 args *certutil.AltNames
822 want *certutil.AltNames
823 }{
824 {
825 &certutil.AltNames{},
826 &certutil.AltNames{},
827 },
828 {
829 &certutil.AltNames{
830 DNSNames: []string{"a", "a"},
831 IPs: []net.IP{{127, 0, 0, 1}},
832 },
833 &certutil.AltNames{
834 DNSNames: []string{"a"},
835 IPs: []net.IP{{127, 0, 0, 1}},
836 },
837 },
838 {
839 &certutil.AltNames{
840 DNSNames: []string{"a"},
841 IPs: []net.IP{{127, 0, 0, 1}, {127, 0, 0, 1}},
842 },
843 &certutil.AltNames{
844 DNSNames: []string{"a"},
845 IPs: []net.IP{{127, 0, 0, 1}},
846 },
847 },
848 {
849 &certutil.AltNames{
850 DNSNames: []string{"a", "a"},
851 IPs: []net.IP{{127, 0, 0, 1}, {127, 0, 0, 1}},
852 },
853 &certutil.AltNames{
854 DNSNames: []string{"a"},
855 IPs: []net.IP{{127, 0, 0, 1}},
856 },
857 },
858 }
859 for _, tt := range tests {
860 RemoveDuplicateAltNames(tt.args)
861 if !reflect.DeepEqual(tt.args, tt.want) {
862 t.Errorf("Wanted %v, got %v", tt.want, tt.args)
863 }
864 }
865 }
866
867 func TestVerifyCertChain(t *testing.T) {
868 tmpdir, err := os.MkdirTemp("", "")
869 if err != nil {
870 t.Fatalf("Couldn't create tmpdir")
871 }
872 defer os.RemoveAll(tmpdir)
873
874 rootCert2, rootKey2, err := NewCertificateAuthority(&CertConfig{
875 Config: certutil.Config{CommonName: "Root CA 2"},
876 })
877 if err != nil {
878 t.Errorf("failed to create root CA cert and key with an error: %v", err)
879 }
880
881 intCert2, intKey2, err := NewIntermediateCertificateAuthority(rootCert2, rootKey2, &CertConfig{
882 Config: certutil.Config{
883 CommonName: "Intermediate CA 2",
884 Usages: []x509.ExtKeyUsage{},
885 },
886 })
887 if err != nil {
888 t.Errorf("failed to create intermediate CA cert and key with an error: %v", err)
889 }
890
891 leafCert2, _, err := NewCertAndKey(intCert2, intKey2, &CertConfig{
892 Config: certutil.Config{
893 CommonName: "Leaf Certificate 2",
894 Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
895 },
896 })
897 if err != nil {
898 t.Errorf("failed to create leaf cert and key with an error: %v", err)
899 }
900
901 var tests = []struct {
902 desc string
903 leaf *x509.Certificate
904 intermediates []*x509.Certificate
905 root *x509.Certificate
906 expected bool
907 }{
908 {
909 desc: "without any intermediate CAs",
910 leaf: servCert,
911 intermediates: []*x509.Certificate{},
912 root: rootCACert,
913 expected: true,
914 },
915 {
916 desc: "missing intermediate CA",
917 leaf: leafCert2,
918 intermediates: []*x509.Certificate{},
919 root: rootCert2,
920 expected: false,
921 },
922 {
923 desc: "with one intermediate CA",
924 leaf: leafCert2,
925 intermediates: []*x509.Certificate{intCert2},
926 root: rootCert2,
927 expected: true,
928 },
929 }
930 for _, rt := range tests {
931 t.Run(rt.desc, func(t *testing.T) {
932 actual := VerifyCertChain(rt.leaf, rt.intermediates, rt.root)
933 if (actual == nil) != rt.expected {
934 t.Errorf(
935 "failed VerifyCertChain:\n\texpected: %t\n\t actual: %t",
936 rt.expected,
937 (actual == nil),
938 )
939 }
940 })
941 }
942 }
943
944 func TestRSAKeySizeFromAlgorithmType(t *testing.T) {
945 var tests = []struct {
946 algorithm kubeadmapi.EncryptionAlgorithmType
947 expectedSize int
948 }{
949 {algorithm: "unknown", expectedSize: 0},
950 {algorithm: "", expectedSize: 2048},
951 {algorithm: kubeadmapi.EncryptionAlgorithmRSA2048, expectedSize: 2048},
952 {algorithm: kubeadmapi.EncryptionAlgorithmRSA3072, expectedSize: 3072},
953 {algorithm: kubeadmapi.EncryptionAlgorithmRSA4096, expectedSize: 4096},
954 }
955 for _, rt := range tests {
956 t.Run(string(rt.algorithm), func(t *testing.T) {
957 size := rsaKeySizeFromAlgorithmType(rt.algorithm)
958 if size != rt.expectedSize {
959 t.Errorf("expected size: %d, got: %d", rt.expectedSize, size)
960 }
961 })
962 }
963 }
964
View as plain text