123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- package cert
- import (
- "crypto"
- "crypto/rand"
- "crypto/rsa"
- "crypto/x509"
- "crypto/x509/pkix"
- "encoding/pem"
- "errors"
- "fmt"
- "math"
- "math/big"
- "net"
- "time"
- "k8s.io/client-go/util/cert"
- "k8s.io/client-go/util/keyutil"
- )
- type SelfSignedCertGenerator struct {
- caKey []byte
- caCert []byte
- }
- var _ CertGenerator = &SelfSignedCertGenerator{}
- // SetCA sets the PEM-encoded CA private key and CA cert for signing the generated serving cert.
- func (cp *SelfSignedCertGenerator) SetCA(caKey, caCert []byte) {
- cp.caKey = caKey
- cp.caCert = caCert
- }
- // Generate creates and returns a CA certificate, certificate and
- // key for the server or client. Key and Cert are used by the server or client
- // to establish trust for others, CA certificate is used by the
- // client or server to verify the other's authentication chain.
- // The cert will be valid for 365 days.
- func (cp *SelfSignedCertGenerator) Generate(commonName string) (*Artifacts, error) {
- var signingKey *rsa.PrivateKey
- var signingCert *x509.Certificate
- var valid bool
- var err error
- valid, signingKey, signingCert = cp.validCACert()
- if !valid {
- signingKey, err = NewPrivateKey()
- if err != nil {
- return nil, fmt.Errorf("failed to create the CA private key: %v", err)
- }
- signingCert, err = cert.NewSelfSignedCACert(cert.Config{CommonName: commonName}, signingKey)
- if err != nil {
- return nil, fmt.Errorf("failed to create the CA cert: %v", err)
- }
- }
- hostIP := net.ParseIP(commonName)
- var altIPs []net.IP
- DNSNames := []string{"localhost"}
- if hostIP.To4() != nil {
- altIPs = append(altIPs, hostIP.To4())
- } else {
- DNSNames = append(DNSNames, commonName)
- }
- key, err := NewPrivateKey()
- if err != nil {
- return nil, fmt.Errorf("failed to create the private key: %v", err)
- }
- signedCert, err := NewSignedCert(
- cert.Config{
- CommonName: commonName,
- Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
- AltNames: cert.AltNames{IPs: altIPs, DNSNames: DNSNames},
- },
- key, signingCert, signingKey,
- )
- if err != nil {
- return nil, fmt.Errorf("failed to create the cert: %v", err)
- }
- return &Artifacts{
- Key: EncodePrivateKeyPEM(key),
- Cert: EncodeCertPEM(signedCert),
- CAKey: EncodePrivateKeyPEM(signingKey),
- CACert: EncodeCertPEM(signingCert),
- }, nil
- }
- func (cp *SelfSignedCertGenerator) validCACert() (bool, *rsa.PrivateKey, *x509.Certificate) {
- if !ValidCACert(cp.caKey, cp.caCert, cp.caCert, "",
- time.Now().AddDate(1, 0, 0)) {
- return false, nil, nil
- }
- var ok bool
- key, err := keyutil.ParsePrivateKeyPEM(cp.caKey)
- if err != nil {
- return false, nil, nil
- }
- privateKey, ok := key.(*rsa.PrivateKey)
- if !ok {
- return false, nil, nil
- }
- certs, err := cert.ParseCertsPEM(cp.caCert)
- if err != nil {
- return false, nil, nil
- }
- if len(certs) != 1 {
- return false, nil, nil
- }
- return true, privateKey, certs[0]
- }
- // NewPrivateKey creates an RSA private key
- func NewPrivateKey() (*rsa.PrivateKey, error) {
- return rsa.GenerateKey(rand.Reader, 2048)
- }
- // NewSignedCert creates a signed certificate using the given CA certificate and key
- func NewSignedCert(cfg cert.Config, key crypto.Signer, caCert *x509.Certificate, caKey crypto.Signer) (*x509.Certificate, error) {
- serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64))
- if err != nil {
- return nil, err
- }
- if len(cfg.CommonName) == 0 {
- return nil, errors.New("must specify a CommonName")
- }
- if len(cfg.Usages) == 0 {
- return nil, errors.New("must specify at least one ExtKeyUsage")
- }
- certTmpl := x509.Certificate{
- Subject: pkix.Name{
- CommonName: cfg.CommonName,
- Organization: cfg.Organization,
- },
- DNSNames: cfg.AltNames.DNSNames,
- IPAddresses: cfg.AltNames.IPs,
- SerialNumber: serial,
- NotBefore: caCert.NotBefore,
- NotAfter: time.Now().Add(time.Hour * 24 * 365 * 10).UTC(),
- KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
- ExtKeyUsage: cfg.Usages,
- }
- certDERBytes, err := x509.CreateCertificate(rand.Reader, &certTmpl, caCert, key.Public(), caKey)
- if err != nil {
- return nil, err
- }
- return x509.ParseCertificate(certDERBytes)
- }
- // EncodePrivateKeyPEM returns PEM-encoded private key data
- func EncodePrivateKeyPEM(key *rsa.PrivateKey) []byte {
- block := pem.Block{
- Type: keyutil.RSAPrivateKeyBlockType,
- Bytes: x509.MarshalPKCS1PrivateKey(key),
- }
- return pem.EncodeToMemory(&block)
- }
- // EncodeCertPEM returns PEM-encoded certificate data
- func EncodeCertPEM(ct *x509.Certificate) []byte {
- block := pem.Block{
- Type: cert.CertificateBlockType,
- Bytes: ct.Raw,
- }
- return pem.EncodeToMemory(&block)
- }
|