github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/integration/ca/ca.go (about)

     1  package ca
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"crypto/elliptic"
     6  	"crypto/rand"
     7  	"crypto/x509"
     8  	"crypto/x509/pkix"
     9  	"encoding/pem"
    10  	"math/big"
    11  	"os"
    12  	"time"
    13  
    14  	"github.com/grafana/dskit/runutil"
    15  )
    16  
    17  type CA struct {
    18  	key    *ecdsa.PrivateKey
    19  	cert   *x509.Certificate
    20  	serial *big.Int
    21  }
    22  
    23  func New(name string) *CA {
    24  	key, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
    25  	if err != nil {
    26  		panic(err)
    27  	}
    28  
    29  	return &CA{
    30  		key: key,
    31  		cert: &x509.Certificate{
    32  			SerialNumber: big.NewInt(1),
    33  			Subject: pkix.Name{
    34  				Organization: []string{name},
    35  			},
    36  			NotBefore: time.Now(),
    37  			NotAfter:  time.Now().Add(time.Hour * 24 * 180),
    38  
    39  			KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
    40  			ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
    41  			BasicConstraintsValid: true,
    42  			IsCA:                  true,
    43  		},
    44  		serial: big.NewInt(2),
    45  	}
    46  
    47  }
    48  
    49  func writeExclusivePEMFile(path, marker string, mode os.FileMode, data []byte) (err error) {
    50  	f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, mode)
    51  	if err != nil {
    52  		return err
    53  	}
    54  	defer runutil.CloseWithErrCapture(&err, f, "write pem file")
    55  
    56  	if err := pem.Encode(f, &pem.Block{Type: marker, Bytes: data}); err != nil {
    57  		return err
    58  	}
    59  	return nil
    60  }
    61  
    62  func (ca *CA) WriteCACertificate(path string) error {
    63  	derBytes, err := x509.CreateCertificate(rand.Reader, ca.cert, ca.cert, ca.key.Public(), ca.key)
    64  	if err != nil {
    65  		return err
    66  	}
    67  
    68  	return writeExclusivePEMFile(path, "CERTIFICATE", 0644, derBytes)
    69  }
    70  
    71  func (ca *CA) WriteCertificate(template *x509.Certificate, certPath string, keyPath string) error {
    72  	key, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
    73  	if err != nil {
    74  		return err
    75  	}
    76  
    77  	keyBytes, err := x509.MarshalECPrivateKey(key)
    78  	if err != nil {
    79  		return err
    80  	}
    81  
    82  	if err := writeExclusivePEMFile(keyPath, "PRIVATE KEY", 0600, keyBytes); err != nil {
    83  		return err
    84  	}
    85  
    86  	template.IsCA = false
    87  	template.NotBefore = time.Now()
    88  	if template.NotAfter.IsZero() {
    89  		template.NotAfter = time.Now().Add(time.Hour * 24 * 180)
    90  	}
    91  	template.SerialNumber = ca.serial.Add(ca.serial, big.NewInt(1))
    92  
    93  	derBytes, err := x509.CreateCertificate(rand.Reader, template, ca.cert, key.Public(), ca.key)
    94  	if err != nil {
    95  		return err
    96  	}
    97  
    98  	return writeExclusivePEMFile(certPath, "CERTIFICATE", 0644, derBytes)
    99  }