github.com/oam-dev/cluster-gateway@v1.9.0/pkg/util/cert/cert.go (about)

     1  package cert
     2  
     3  import (
     4  	"context"
     5  	"crypto/rand"
     6  	"crypto/rsa"
     7  	"crypto/x509"
     8  	"encoding/pem"
     9  
    10  	"github.com/oam-dev/cluster-gateway/pkg/common"
    11  	"github.com/openshift/library-go/pkg/crypto"
    12  	"github.com/pkg/errors"
    13  	corev1 "k8s.io/api/core/v1"
    14  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    15  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    16  	"k8s.io/client-go/kubernetes"
    17  	"k8s.io/client-go/rest"
    18  	"k8s.io/client-go/util/cert"
    19  )
    20  
    21  var (
    22  	rsaKeySize = 2048 // a decent number, as of 2019
    23  )
    24  
    25  func EnsureCAPair(cfg *rest.Config, namespace, name string) (*crypto.CA, error) {
    26  	c, err := kubernetes.NewForConfig(cfg)
    27  	if err != nil {
    28  		return nil, err
    29  	}
    30  	generate := false
    31  	current, err := c.CoreV1().
    32  		Secrets(namespace).
    33  		Get(context.TODO(), name, metav1.GetOptions{})
    34  	if err != nil {
    35  		if !apierrors.IsNotFound(err) {
    36  			return nil, err
    37  		}
    38  		generate = true
    39  	}
    40  
    41  	if !generate {
    42  		caCertData := current.Data["ca.crt"]
    43  		caKeyData := current.Data["ca.key"]
    44  		certBlock, _ := pem.Decode(caCertData)
    45  		caCert, err := x509.ParseCertificate(certBlock.Bytes)
    46  		if err != nil {
    47  			return nil, errors.Wrapf(err, "failed to parse ca certificate")
    48  		}
    49  		keyBlock, _ := pem.Decode(caKeyData)
    50  		caKey, err := x509.ParsePKCS8PrivateKey(keyBlock.Bytes)
    51  		if err != nil {
    52  			return nil, errors.Wrapf(err, "failed to parse ca key")
    53  		}
    54  		return &crypto.CA{
    55  			Config: &crypto.TLSCertificateConfig{
    56  				Certs: []*x509.Certificate{caCert},
    57  				Key:   caKey,
    58  			},
    59  			SerialGenerator: &crypto.RandomSerialGenerator{},
    60  		}, nil
    61  	}
    62  
    63  	privateKey, err := rsa.GenerateKey(rand.Reader, rsaKeySize)
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  	caCert, err := cert.NewSelfSignedCACert(cert.Config{
    68  		CommonName: common.AddonName,
    69  	}, privateKey)
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  	rawKeyData, err := x509.MarshalPKCS8PrivateKey(privateKey)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  	if _, err := c.CoreV1().
    78  		Secrets(namespace).
    79  		Create(context.TODO(), &corev1.Secret{
    80  			ObjectMeta: metav1.ObjectMeta{
    81  				Namespace: namespace,
    82  				Name:      name,
    83  			},
    84  			Data: map[string][]byte{
    85  				"ca.crt": pem.EncodeToMemory(&pem.Block{
    86  					Type:  "CERTIFICATE",
    87  					Bytes: caCert.Raw,
    88  				}),
    89  				"ca.key": pem.EncodeToMemory(&pem.Block{
    90  					Type:  "PRIVATE KEY",
    91  					Bytes: rawKeyData,
    92  				}),
    93  			},
    94  		}, metav1.CreateOptions{}); err != nil {
    95  		return nil, err
    96  	}
    97  	return &crypto.CA{
    98  		Config: &crypto.TLSCertificateConfig{
    99  			Certs: []*x509.Certificate{caCert},
   100  			Key:   privateKey,
   101  		},
   102  		SerialGenerator: &crypto.RandomSerialGenerator{},
   103  	}, nil
   104  }