in internal/certs/certs.go [155:238]
func New(certType int, issuer *Issuer, opts ...Option) (*Certificate, error) {
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, fmt.Errorf("failed to generate key: %w", err)
}
sn, err := newSerialNumber()
if err != nil {
return nil, fmt.Errorf("failed to get a unique serial number: %w", err)
}
// Don't use a expiration time longer than 825 days.
// See https://rahulkj.github.io/openssl,/certificates/2022/09/09/self-signed-certificates.html.
const longTime = 800 * 24 * time.Hour
template := x509.Certificate{
NotBefore: time.Now(),
NotAfter: time.Now().Add(longTime),
SerialNumber: sn,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
BasicConstraintsValid: true,
}
switch certType {
case IssueCertTypeCA:
template.IsCA = true
template.KeyUsage |= x509.KeyUsageCRLSign | x509.KeyUsageCertSign
if issuer == nil {
template.Subject.CommonName = "elastic-package CA"
} else {
template.Subject.CommonName = "intermediate elastic-package CA"
}
case IssueCertTypeClient:
// If the requester is a client we set clientAuth instead
template.ExtKeyUsage = []x509.ExtKeyUsage{
x509.ExtKeyUsageClientAuth,
}
// Include local hostname and ips as alternates in service certificates.
template.DNSNames = []string{"localhost"}
template.IPAddresses = []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")}
case IssueCertTypeService:
template.ExtKeyUsage = []x509.ExtKeyUsage{
// Required for Chrome in OSX to show the "Proceed anyway" link.
// https://stackoverflow.com/a/64309893/28855
x509.ExtKeyUsageServerAuth,
}
// Include local hostname and ips as alternates in service certificates.
template.DNSNames = []string{"localhost"}
template.IPAddresses = []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")}
default:
return nil, fmt.Errorf("unknown certificate type %d", certType)
}
for _, opt := range opts {
opt(&template)
}
// Self-signed unless an issuer has been received.
var parent *x509.Certificate = &template
var signer crypto.Signer = key
var issuerCert *Certificate
if issuer != nil {
parent = issuer.cert
signer = issuer.key
issuerCert = issuer.Certificate
template.Issuer = issuer.cert.Subject
}
der, err := x509.CreateCertificate(rand.Reader, &template, parent, key.Public(), signer)
if err != nil {
return nil, fmt.Errorf("failed to generate certificate: %w", err)
}
cert, err := x509.ParseCertificate(der)
if err != nil {
return nil, fmt.Errorf("failed to parse certificate: %w", err)
}
return &Certificate{
key: key,
cert: cert,
issuer: issuerCert,
}, nil
}