...

Source file src/sigs.k8s.io/gateway-api/conformance/utils/kubernetes/certificate.go

Documentation: sigs.k8s.io/gateway-api/conformance/utils/kubernetes

     1  /*
     2  Copyright 2022 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 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  	// ensure auth plugins are loaded
    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  // MustCreateSelfSignedCertSecret creates a self-signed SSL certificate and stores it in a secret
    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  // generateRSACert generates a basic self signed certificate valid for a year
    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