@@ -17,16 +17,24 @@ limitations under the License.
17
17
package options
18
18
19
19
import (
20
+ "bytes"
21
+ cryptorand "crypto/rand"
22
+ "crypto/rsa"
20
23
"crypto/tls"
21
24
"crypto/x509"
25
+ "crypto/x509/pkix"
22
26
"encoding/base64"
23
27
"encoding/pem"
24
28
"fmt"
25
29
"io/ioutil"
30
+ "math/big"
26
31
"net"
27
32
"os"
33
+ "path/filepath"
28
34
"reflect"
35
+ "strings"
29
36
"testing"
37
+ "time"
30
38
31
39
"github.com/stretchr/testify/assert"
32
40
@@ -39,7 +47,6 @@ import (
39
47
utilflag "k8s.io/apiserver/pkg/util/flag"
40
48
"k8s.io/client-go/discovery"
41
49
restclient "k8s.io/client-go/rest"
42
- utilcert "k8s.io/client-go/util/cert"
43
50
)
44
51
45
52
func setUp (t * testing.T ) Config {
@@ -387,16 +394,17 @@ func TestServerRunWithSNI(t *testing.T) {
387
394
},
388
395
}
389
396
390
- tempDir , err := ioutil .TempDir ("" , "" )
391
- if err != nil {
392
- t .Fatal (err )
397
+ specToName := func (spec TestCertSpec ) string {
398
+ return spec .host + "_" + strings .Join (spec .names , "," ) + "_" + strings .Join (spec .ips , "," )
393
399
}
394
- defer os .RemoveAll (tempDir )
395
400
396
401
NextTest:
397
402
for title , test := range tests {
398
403
// create server cert
399
- serverCertBundleFile , serverKeyFile , err := createTestCertFiles (tempDir , test .Cert )
404
+ certDir := "testdata/" + specToName (test .Cert )
405
+ serverCertBundleFile := filepath .Join (certDir , "cert" )
406
+ serverKeyFile := filepath .Join (certDir , "key" )
407
+ err := getOrCreateTestCertFiles (serverCertBundleFile , serverKeyFile , test .Cert )
400
408
if err != nil {
401
409
t .Errorf ("%q - failed to create server cert: %v" , title , err )
402
410
continue NextTest
@@ -419,7 +427,10 @@ NextTest:
419
427
serverSig : - 1 ,
420
428
}
421
429
for j , c := range test .SNICerts {
422
- certBundleFile , keyFile , err := createTestCertFiles (tempDir , c .TestCertSpec )
430
+ sniDir := filepath .Join (certDir , specToName (c .TestCertSpec ))
431
+ certBundleFile := filepath .Join (sniDir , "cert" )
432
+ keyFile := filepath .Join (sniDir , "key" )
433
+ err := getOrCreateTestCertFiles (certBundleFile , keyFile , c .TestCertSpec )
423
434
if err != nil {
424
435
t .Errorf ("%q - failed to create SNI cert %d: %v" , title , j , err )
425
436
continue NextTest
@@ -572,7 +583,7 @@ func parseIPList(ips []string) []net.IP {
572
583
}
573
584
574
585
func createTestTLSCerts (spec TestCertSpec ) (tlsCert tls.Certificate , err error ) {
575
- certPem , keyPem , err := utilcert . GenerateSelfSignedCertKey (spec .host , parseIPList (spec .ips ), spec .names )
586
+ certPem , keyPem , err := generateSelfSignedCertKey (spec .host , parseIPList (spec .ips ), spec .names )
576
587
if err != nil {
577
588
return tlsCert , err
578
589
}
@@ -581,35 +592,31 @@ func createTestTLSCerts(spec TestCertSpec) (tlsCert tls.Certificate, err error)
581
592
return tlsCert , err
582
593
}
583
594
584
- func createTestCertFiles (dir string , spec TestCertSpec ) (certFilePath , keyFilePath string , err error ) {
585
- certPem , keyPem , err := utilcert .GenerateSelfSignedCertKey (spec .host , parseIPList (spec .ips ), spec .names )
586
- if err != nil {
587
- return "" , "" , err
588
- }
589
-
590
- certFile , err := ioutil .TempFile (dir , "cert" )
591
- if err != nil {
592
- return "" , "" , err
595
+ func getOrCreateTestCertFiles (certFileName , keyFileName string , spec TestCertSpec ) (err error ) {
596
+ if _ , err := os .Stat (certFileName ); err == nil {
597
+ if _ , err := os .Stat (keyFileName ); err == nil {
598
+ return nil
599
+ }
593
600
}
594
601
595
- keyFile , err := ioutil . TempFile ( dir , "key" )
602
+ certPem , keyPem , err := generateSelfSignedCertKey ( spec . host , parseIPList ( spec . ips ), spec . names )
596
603
if err != nil {
597
- return "" , "" , err
604
+ return err
598
605
}
599
606
600
- _ , err = certFile .Write (certPem )
607
+ os .MkdirAll (filepath .Dir (certFileName ), os .FileMode (0755 ))
608
+ err = ioutil .WriteFile (certFileName , certPem , os .FileMode (0755 ))
601
609
if err != nil {
602
- return "" , "" , err
610
+ return err
603
611
}
604
- certFile .Close ()
605
612
606
- _ , err = keyFile .Write (keyPem )
613
+ os .MkdirAll (filepath .Dir (keyFileName ), os .FileMode (0755 ))
614
+ err = ioutil .WriteFile (keyFileName , keyPem , os .FileMode (0755 ))
607
615
if err != nil {
608
- return "" , "" , err
616
+ return err
609
617
}
610
- keyFile .Close ()
611
618
612
- return certFile . Name (), keyFile . Name (), nil
619
+ return nil
613
620
}
614
621
615
622
func caCertFromBundle (bundlePath string ) (* x509.Certificate , error ) {
@@ -663,3 +670,55 @@ func fakeVersion() version.Info {
663
670
GitTreeState : "Dirty" ,
664
671
}
665
672
}
673
+
674
+ // generateSelfSignedCertKey creates a self-signed certificate and key for the given host.
675
+ // Host may be an IP or a DNS name
676
+ // You may also specify additional subject alt names (either ip or dns names) for the certificate
677
+ func generateSelfSignedCertKey (host string , alternateIPs []net.IP , alternateDNS []string ) ([]byte , []byte , error ) {
678
+ priv , err := rsa .GenerateKey (cryptorand .Reader , 2048 )
679
+ if err != nil {
680
+ return nil , nil , err
681
+ }
682
+
683
+ template := x509.Certificate {
684
+ SerialNumber : big .NewInt (1 ),
685
+ Subject : pkix.Name {
686
+ CommonName : fmt .Sprintf ("%s@%d" , host , time .Now ().Unix ()),
687
+ },
688
+ NotBefore : time .Unix (0 , 0 ),
689
+ NotAfter : time .Now ().Add (time .Hour * 24 * 365 * 100 ),
690
+
691
+ KeyUsage : x509 .KeyUsageKeyEncipherment | x509 .KeyUsageDigitalSignature | x509 .KeyUsageCertSign ,
692
+ ExtKeyUsage : []x509.ExtKeyUsage {x509 .ExtKeyUsageServerAuth },
693
+ BasicConstraintsValid : true ,
694
+ IsCA : true ,
695
+ }
696
+
697
+ if ip := net .ParseIP (host ); ip != nil {
698
+ template .IPAddresses = append (template .IPAddresses , ip )
699
+ } else {
700
+ template .DNSNames = append (template .DNSNames , host )
701
+ }
702
+
703
+ template .IPAddresses = append (template .IPAddresses , alternateIPs ... )
704
+ template .DNSNames = append (template .DNSNames , alternateDNS ... )
705
+
706
+ derBytes , err := x509 .CreateCertificate (cryptorand .Reader , & template , & template , & priv .PublicKey , priv )
707
+ if err != nil {
708
+ return nil , nil , err
709
+ }
710
+
711
+ // Generate cert
712
+ certBuffer := bytes.Buffer {}
713
+ if err := pem .Encode (& certBuffer , & pem.Block {Type : "CERTIFICATE" , Bytes : derBytes }); err != nil {
714
+ return nil , nil , err
715
+ }
716
+
717
+ // Generate key
718
+ keyBuffer := bytes.Buffer {}
719
+ if err := pem .Encode (& keyBuffer , & pem.Block {Type : "RSA PRIVATE KEY" , Bytes : x509 .MarshalPKCS1PrivateKey (priv )}); err != nil {
720
+ return nil , nil , err
721
+ }
722
+
723
+ return certBuffer .Bytes (), keyBuffer .Bytes (), nil
724
+ }
0 commit comments