| 68 | } |
| 69 | |
| 70 | func (h x509CertsHandler) SignCerts(opts SignCertsOptions) (*pem.Block, error) { |
| 71 | pubkey := opts.publicKey |
| 72 | if opts.csrDER != nil { |
| 73 | csr, err := x509.ParseCertificateRequest(opts.csrDER) |
| 74 | if err != nil { |
| 75 | return nil, fmt.Errorf("failed to parse csr, err: %v", err) |
| 76 | } |
| 77 | opts.cfg.CommonName = csr.Subject.CommonName |
| 78 | opts.cfg.Organization = csr.Subject.Organization |
| 79 | opts.cfg.AltNames.DNSNames = csr.DNSNames |
| 80 | opts.cfg.AltNames.IPs = csr.IPAddresses |
| 81 | pubkey = csr.PublicKey |
| 82 | } |
| 83 | if len(opts.cfg.CommonName) == 0 { |
| 84 | return nil, errors.New("must specify a CommonName") |
| 85 | } |
| 86 | if len(opts.cfg.Usages) == 0 { |
| 87 | return nil, errors.New("must specify at least one ExtKeyUsage") |
| 88 | } |
| 89 | |
| 90 | serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64)) |
| 91 | if err != nil { |
| 92 | return nil, fmt.Errorf("failed to generate serial number, err: %v", err) |
| 93 | } |
| 94 | |
| 95 | caKey, err := x509PrivateKeyWrap{der: opts.caKeyDER}.Signer() |
| 96 | if err != nil { |
| 97 | return nil, fmt.Errorf("failed to parse CA private key, err: %v", err) |
| 98 | } |
| 99 | |
| 100 | ca, err := x509.ParseCertificate(opts.caDER) |
| 101 | if err != nil { |
| 102 | return nil, fmt.Errorf("failed to parse CA, err: %v", err) |
| 103 | } |
| 104 | |
| 105 | certTmpl := x509.Certificate{ |
| 106 | Subject: pkix.Name{ |
| 107 | CommonName: opts.cfg.CommonName, |
| 108 | Organization: opts.cfg.Organization, |
| 109 | }, |
| 110 | DNSNames: opts.cfg.AltNames.DNSNames, |
| 111 | IPAddresses: opts.cfg.AltNames.IPs, |
| 112 | SerialNumber: serial, |
| 113 | NotBefore: time.Now().UTC(), |
| 114 | NotAfter: time.Now().Add(opts.expiration), |
| 115 | KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, |
| 116 | ExtKeyUsage: opts.cfg.Usages, |
| 117 | } |
| 118 | certDER, err := x509.CreateCertificate(rand.Reader, &certTmpl, ca, pubkey, caKey) |
| 119 | if err != nil { |
| 120 | return nil, fmt.Errorf("failed to create certificate, err: %v", err) |
| 121 | } |
| 122 | |
| 123 | return &pem.Block{Type: certutil.CertificateBlockType, Bytes: certDER}, nil |
| 124 | } |