k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/cmd/kubeadm/app/util/pkiutil/pki_helpers_test.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 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 // TestMain generates the bellow certs and keys so that 40 // they are reused in tests whenever possible 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 // Override NewPrivateKey to reuse the same key for all certs 113 // since this test is only checking cert.ExtKeyUsage 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 // rootCACert is treated as an intermediate CA here 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 }