1
16
17 package kubernetes
18
19 import (
20 "bytes"
21 "crypto/rand"
22 "crypto/rsa"
23 "crypto/x509"
24 "crypto/x509/pkix"
25 "encoding/pem"
26 "fmt"
27 "io"
28 "math/big"
29 "net"
30 "testing"
31 "time"
32
33 "github.com/stretchr/testify/require"
34 corev1 "k8s.io/api/core/v1"
35 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
36
37
38 _ "k8s.io/client-go/plugin/pkg/client/auth"
39 )
40
41 const (
42 rsaBits = 2048
43 validFor = 365 * 24 * time.Hour
44 )
45
46
47 func MustCreateSelfSignedCertSecret(t *testing.T, namespace, secretName string, hosts []string) *corev1.Secret {
48 require.Greater(t, len(hosts), 0, "require a non-empty hosts for Subject Alternate Name values")
49
50 var serverKey, serverCert bytes.Buffer
51
52 require.NoError(t, generateRSACert(hosts, &serverKey, &serverCert), "failed to generate RSA certificate")
53
54 data := map[string][]byte{
55 corev1.TLSCertKey: serverCert.Bytes(),
56 corev1.TLSPrivateKeyKey: serverKey.Bytes(),
57 }
58
59 newSecret := &corev1.Secret{
60 ObjectMeta: metav1.ObjectMeta{
61 Namespace: namespace,
62 Name: secretName,
63 },
64 Type: corev1.SecretTypeTLS,
65 Data: data,
66 }
67
68 return newSecret
69 }
70
71
72 func generateRSACert(hosts []string, keyOut, certOut io.Writer) error {
73 priv, err := rsa.GenerateKey(rand.Reader, rsaBits)
74 if err != nil {
75 return fmt.Errorf("failed to generate key: %w", err)
76 }
77 notBefore := time.Now()
78 notAfter := notBefore.Add(validFor)
79
80 serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
81 serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
82 if err != nil {
83 return fmt.Errorf("failed to generate serial number: %w", err)
84 }
85
86 template := x509.Certificate{
87 SerialNumber: serialNumber,
88 Subject: pkix.Name{
89 CommonName: "default",
90 Organization: []string{"Acme Co"},
91 },
92 NotBefore: notBefore,
93 NotAfter: notAfter,
94
95 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
96 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
97 BasicConstraintsValid: true,
98 }
99
100 for _, h := range hosts {
101 if ip := net.ParseIP(h); ip != nil {
102 template.IPAddresses = append(template.IPAddresses, ip)
103 } else {
104 template.DNSNames = append(template.DNSNames, h)
105 }
106 }
107
108 derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
109 if err != nil {
110 return fmt.Errorf("failed to create certificate: %w", err)
111 }
112
113 if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
114 return fmt.Errorf("failed creating cert: %w", err)
115 }
116
117 if err := pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil {
118 return fmt.Errorf("failed creating key: %w", err)
119 }
120
121 return nil
122 }
123
View as plain text