github.com/percona/percona-xtradb-cluster-operator@v1.14.0/pkg/pxctls/pxctls.go (about)

     1  package pxctls
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/rand"
     6  	"crypto/rsa"
     7  	"crypto/x509"
     8  	"crypto/x509/pkix"
     9  	"encoding/pem"
    10  	"fmt"
    11  	"math/big"
    12  	"time"
    13  )
    14  
    15  var validityNotAfter = time.Now().Add(time.Hour * 24 * 365)
    16  
    17  // Issue returns CA certificate, TLS certificate and TLS private key
    18  func Issue(hosts []string) (caCert []byte, tlsCert []byte, tlsKey []byte, err error) {
    19  	rsaBits := 2048
    20  	priv, err := rsa.GenerateKey(rand.Reader, rsaBits)
    21  	if err != nil {
    22  		return nil, nil, nil, fmt.Errorf("generate rsa key: %v", err)
    23  	}
    24  	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
    25  	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
    26  	if err != nil {
    27  		return nil, nil, nil, fmt.Errorf("generate serial number for root: %v", err)
    28  	}
    29  	subject := pkix.Name{
    30  		Organization: []string{"Root CA"},
    31  	}
    32  	issuer := pkix.Name{
    33  		Organization: []string{"Root CA"},
    34  	}
    35  	caTemplate := x509.Certificate{
    36  		SerialNumber:          serialNumber,
    37  		Subject:               subject,
    38  		NotBefore:             time.Now(),
    39  		NotAfter:              validityNotAfter,
    40  		KeyUsage:              x509.KeyUsageCertSign,
    41  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
    42  		BasicConstraintsValid: true,
    43  		IsCA:                  true,
    44  	}
    45  
    46  	derBytes, err := x509.CreateCertificate(rand.Reader, &caTemplate, &caTemplate, &priv.PublicKey, priv)
    47  	if err != nil {
    48  		return nil, nil, nil, fmt.Errorf("generate CA certificate: %v", err)
    49  	}
    50  	certOut := &bytes.Buffer{}
    51  	err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
    52  	if err != nil {
    53  		return nil, nil, nil, fmt.Errorf("encode CA certificate: %v", err)
    54  	}
    55  	cert := certOut.Bytes()
    56  
    57  	serialNumber, err = rand.Int(rand.Reader, serialNumberLimit)
    58  	if err != nil {
    59  		return nil, nil, nil, fmt.Errorf("generate serial number for client: %v", err)
    60  	}
    61  	subject = pkix.Name{
    62  		Organization: []string{"PXC"},
    63  	}
    64  	tlsTemplate := x509.Certificate{
    65  		SerialNumber:          serialNumber,
    66  		Subject:               subject,
    67  		Issuer:                issuer,
    68  		NotBefore:             time.Now(),
    69  		NotAfter:              validityNotAfter,
    70  		DNSNames:              hosts,
    71  		KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
    72  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
    73  		BasicConstraintsValid: true,
    74  		IsCA:                  false,
    75  	}
    76  	clientKey, err := rsa.GenerateKey(rand.Reader, 2048)
    77  	if err != nil {
    78  		return nil, nil, nil, fmt.Errorf("generate client key: %v", err)
    79  	}
    80  	tlsDerBytes, err := x509.CreateCertificate(rand.Reader, &tlsTemplate, &caTemplate, &clientKey.PublicKey, priv)
    81  	if err != nil {
    82  		return nil, nil, nil, err
    83  	}
    84  	tlsCertOut := &bytes.Buffer{}
    85  	err = pem.Encode(tlsCertOut, &pem.Block{Type: "CERTIFICATE", Bytes: tlsDerBytes})
    86  	if err != nil {
    87  		return nil, nil, nil, fmt.Errorf("encode TLS  certificate: %v", err)
    88  	}
    89  	tlsCert = tlsCertOut.Bytes()
    90  
    91  	keyOut := &bytes.Buffer{}
    92  	block := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(clientKey)}
    93  	err = pem.Encode(keyOut, block)
    94  	if err != nil {
    95  		return nil, nil, nil, fmt.Errorf("encode RSA private key: %v", err)
    96  	}
    97  	privKey := keyOut.Bytes()
    98  
    99  	return cert, tlsCert, privKey, nil
   100  }