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 }