github.com/kubernetes-incubator/kube-aws@v0.16.4/pki/pki.go (about)

     1  package pki
     2  
     3  import (
     4  	"crypto/rand"
     5  	"crypto/rsa"
     6  	"crypto/x509"
     7  	"crypto/x509/pkix"
     8  	"errors"
     9  	"fmt"
    10  	"math"
    11  	"math/big"
    12  	"net"
    13  	"time"
    14  
    15  	"github.com/kubernetes-incubator/kube-aws/logger"
    16  	"github.com/kubernetes-incubator/kube-aws/pkg/api"
    17  )
    18  
    19  type PKI struct {
    20  }
    21  
    22  func NewPKI() *PKI {
    23  	return &PKI{}
    24  }
    25  
    26  func (pki *PKI) GenerateKeyPair(spec api.KeyPairSpec, signer *KeyPair) (*KeyPair, error) {
    27  	logger.Debugf("GenerateKeyPair - spec: %+v", spec)
    28  	key, err := NewPrivateKey()
    29  	if err != nil {
    30  		return nil, err
    31  	}
    32  
    33  	if spec.Duration <= 0 {
    34  		return nil, errors.New("self-signed CA cert duration must not be negative or zero")
    35  	}
    36  
    37  	keyUsage := x509.KeyUsage(0)
    38  	extKeyUsages := []x509.ExtKeyUsage{}
    39  	isCA := false
    40  	basicConstraintsValid := false
    41  
    42  	for _, u := range spec.Usages {
    43  		switch u {
    44  		case "ca":
    45  			keyUsage = keyUsage | x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign
    46  			isCA = true
    47  			basicConstraintsValid = true
    48  		case "server":
    49  			keyUsage = keyUsage | x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature
    50  			extKeyUsages = append(extKeyUsages, x509.ExtKeyUsageServerAuth)
    51  		case "client":
    52  			keyUsage = keyUsage | x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature
    53  			extKeyUsages = append(extKeyUsages, x509.ExtKeyUsageClientAuth)
    54  		default:
    55  			return nil, fmt.Errorf("unsupported usage \"%s\". expected any combination of \"ca\", \"server\", \"client\"", u)
    56  		}
    57  	}
    58  
    59  	serialNumber, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64))
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  
    64  	ips := make([]net.IP, len(spec.IPAddresses))
    65  	for i, ipStr := range spec.IPAddresses {
    66  		ips[i] = net.ParseIP(ipStr)
    67  	}
    68  
    69  	logger.Debugf("Generating x509 certificate template")
    70  	tmpl := x509.Certificate{
    71  		SerialNumber: serialNumber,
    72  		Subject: pkix.Name{
    73  			CommonName:   spec.CommonName,
    74  			Organization: []string{spec.Organization},
    75  		},
    76  		NotBefore:             time.Now().UTC(),
    77  		NotAfter:              time.Now().Add(spec.Duration).UTC(),
    78  		KeyUsage:              keyUsage,
    79  		DNSNames:              spec.DNSNames,
    80  		IPAddresses:           ips,
    81  		ExtKeyUsage:           extKeyUsages,
    82  		BasicConstraintsValid: basicConstraintsValid,
    83  		IsCA:                  isCA,
    84  	}
    85  
    86  	// handle self-signed/CA certificates or certs signed by a CA
    87  	var signerCert *x509.Certificate
    88  	var signerKey *rsa.PrivateKey
    89  	if signer == nil {
    90  		if spec.Signer != "" {
    91  			return nil, fmt.Errorf("The certificate spec includes a signer but singer KeyPair is missing")
    92  		}
    93  		logger.Debugf("This certificate is going to be self-signed!")
    94  		signerCert = &tmpl
    95  		signerKey = key
    96  	} else {
    97  		signerCert = signer.Cert
    98  		signerKey = signer.Key
    99  	}
   100  
   101  	logger.Debugf("Creating x509 certificate...")
   102  	certAsn1DERData, err := x509.CreateCertificate(rand.Reader, &tmpl, signerCert, key.Public(), signerKey)
   103  	if err != nil {
   104  		return nil, err
   105  	}
   106  	cert, err := x509.ParseCertificate(certAsn1DERData)
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  
   111  	logger.Debugf("returning keypair..")
   112  	return &KeyPair{Key: key, Cert: cert}, nil
   113  }