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 }