author | Alberto Bertogli
<albertito@blitiri.com.ar> 2022-08-28 01:05:42 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2022-08-28 01:05:42 UTC |
parent | ba839c42483a91f4d405ecf489cac36e93a5256f |
test/util/generate_cert.go | +72 | -67 |
test/util/lib.sh | +1 | -1 |
diff --git a/test/util/generate_cert.go b/test/util/generate_cert.go index 07daed7..99c5e0d 100644 --- a/test/util/generate_cert.go +++ b/test/util/generate_cert.go @@ -1,24 +1,21 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - //go:build ignore // +build ignore -// Generate a self-signed X.509 certificate for a TLS server. Outputs to -// 'cert.pem' and 'key.pem' and will overwrite existing files. - +// Utility to generate self-signed certificates. +// It generates a self-signed x509 certificate and key pair, and writes them +// to "fullchain.pem" and "privkey.pem". +// +// Intended for use in tests, not for production use. package main import ( - "crypto/rand" + crand "crypto/rand" "crypto/rsa" "crypto/x509" "crypto/x509/pkix" "encoding/pem" "flag" "fmt" - "log" "math/big" "net" "os" @@ -27,90 +24,98 @@ import ( ) var ( - host = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for") - validFrom = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011") - validFor = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for") - isCA = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority") + host = flag.String("host", "", + "Hostnames/IPs to generate the certificate for (comma separated)") + validFor = flag.Duration("validfor", 4*time.Hour, + "How long will the certificate be valid for") + isCA = flag.Bool("ca", false, + "Should this cert be its own CA?") ) +func fatalf(f string, a ...interface{}) { + fmt.Printf(f, a...) + os.Exit(1) +} + func main() { flag.Parse() - - if len(*host) == 0 { - log.Fatalf("Missing required --host parameter") + if *host == "" { + fatalf("Required flag: --host") } - priv, err := rsa.GenerateKey(rand.Reader, 2048) + // Build the certificate template. + serial, err := crand.Int(crand.Reader, big.NewInt(1<<62)) if err != nil { - log.Fatalf("failed to generate private key: %s", err) + fatalf("Error generating serial number: %v\n", err) } + tmpl := x509.Certificate{ + SerialNumber: serial, + Subject: pkix.Name{Organization: []string{"Test Cert Org"}}, - var notBefore time.Time - if len(*validFrom) == 0 { - notBefore = time.Now() - } else { - notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom) - if err != nil { - fmt.Fprintf(os.Stderr, "Failed to parse creation date: %s\n", err) - os.Exit(1) - } - } + // Valid from now until `--validfor` in the future. + // Extended certs can be useful for manual troubleshooting. + NotBefore: time.Now(), + NotAfter: time.Now().Add(*validFor), - notAfter := notBefore.Add(*validFor) + KeyUsage: x509.KeyUsageKeyEncipherment | + x509.KeyUsageDigitalSignature | + x509.KeyUsageCertSign, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) - serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) - if err != nil { - log.Fatalf("failed to generate serial number: %s", err) + BasicConstraintsValid: true, } - template := x509.Certificate{ - SerialNumber: serialNumber, - Subject: pkix.Name{ - Organization: []string{"Acme Co"}, - }, - NotBefore: notBefore, - NotAfter: notAfter, - - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - BasicConstraintsValid: true, + if *isCA { + tmpl.IsCA = true } hosts := strings.Split(*host, ",") for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { - template.IPAddresses = append(template.IPAddresses, ip) + tmpl.IPAddresses = append(tmpl.IPAddresses, ip) } else { - template.DNSNames = append(template.DNSNames, h) + tmpl.DNSNames = append(tmpl.DNSNames, h) } } - if *isCA { - template.IsCA = true - template.KeyUsage |= x509.KeyUsageCertSign - } - - derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) + // Generate a private key (RSA 2048). + privK, err := rsa.GenerateKey(crand.Reader, 2048) if err != nil { - log.Fatalf("Failed to create certificate: %s", err) + fatalf("Error generating key: %v\n", err) } - certOut, err := os.Create("fullchain.pem") - if err != nil { - log.Fatalf("failed to open fullchain.pem for writing: %s", err) - } - pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) - certOut.Close() + // Write the certificate. + { + derBytes, err := x509.CreateCertificate( + crand.Reader, &tmpl, &tmpl, &privK.PublicKey, privK) + if err != nil { + fatalf("Failed to create certificate: %v\n", err) + } - keyOut, err := os.OpenFile("privkey.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) - if err != nil { - log.Fatalf("failed to open privkey.pem for writing: %s", err) - return + fullchain, err := os.Create("fullchain.pem") + if err != nil { + fatalf("Failed to open fullchain.pem: %v\n", err) + } + err = pem.Encode(fullchain, + &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + if err != nil { + fatalf("Error encoding certificate: %v\n", err) + } + fullchain.Close() } - block := &pem.Block{Type: "RSA PRIVATE KEY", - Bytes: x509.MarshalPKCS1PrivateKey(priv)} - pem.Encode(keyOut, block) - keyOut.Close() + // Write the private key. + { + privkey, err := os.Create("privkey.pem") + if err != nil { + fatalf("failed to open privkey.pem: %v\n", err) + } + block := &pem.Block{Type: "RSA PRIVATE KEY", + Bytes: x509.MarshalPKCS1PrivateKey(privK)} + err = pem.Encode(privkey, block) + if err != nil { + fatalf("Error encoding private key: %v\n", err) + } + privkey.Close() + } } diff --git a/test/util/lib.sh b/test/util/lib.sh index 6ba248c..4a0adb5 100644 --- a/test/util/lib.sh +++ b/test/util/lib.sh @@ -65,7 +65,7 @@ function generate_certs() { ( cd .certs/localhost go run ${UTILDIR}/generate_cert.go \ - -ca -duration=1h --host=localhost + -ca -validfor=1h --host=localhost ) }