88 lines
1.8 KiB
Go
88 lines
1.8 KiB
Go
package csr
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"crypto/x509"
|
|
"crypto/x509/pkix"
|
|
"encoding/pem"
|
|
"fmt"
|
|
"net"
|
|
"os"
|
|
|
|
"github.com/spf13/cobra"
|
|
"src.lwithers.me.uk/go/rsa/pkg/pemfile"
|
|
)
|
|
|
|
var (
|
|
outputFile string
|
|
hostnames []string
|
|
ips []string
|
|
)
|
|
|
|
// Register the "keygen" subcommand.
|
|
func Register(root *cobra.Command) {
|
|
cmd := &cobra.Command{
|
|
Use: "csr key.pem \"description (common name)\"",
|
|
Short: "Generate a certificate signing request",
|
|
Run: CSR,
|
|
Args: cobra.ExactArgs(2),
|
|
}
|
|
|
|
cmd.Flags().StringVarP(&outputFile, "output", "o", "", "Name of output file (defaults to stdout)")
|
|
cmd.Flags().StringArrayVar(&hostnames, "host", nil, "Subject alternate name (may be specified multiple times)")
|
|
cmd.Flags().StringArrayVar(&ips, "ip", nil, "IP address (may be specified multiple times)")
|
|
|
|
root.AddCommand(cmd)
|
|
}
|
|
|
|
// CSR will load a private key, then write out and generate a CSR.
|
|
func CSR(cmd *cobra.Command, args []string) {
|
|
keyFile := args[0]
|
|
desc := args[1]
|
|
|
|
key, err := pemfile.ReadKey(keyFile)
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
var ipAddrs []net.IP
|
|
for _, ip := range ips {
|
|
i := net.ParseIP(ip)
|
|
if i == nil {
|
|
fmt.Fprintf(os.Stderr, "--ip argument %q is not valid\n", ip)
|
|
os.Exit(1)
|
|
}
|
|
ipAddrs = append(ipAddrs, i)
|
|
}
|
|
|
|
template := &x509.CertificateRequest{
|
|
Subject: pkix.Name{
|
|
CommonName: desc,
|
|
},
|
|
DNSNames: hostnames,
|
|
IPAddresses: ipAddrs,
|
|
}
|
|
der, err := x509.CreateCertificateRequest(rand.Reader, template, key)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "failed to create certificate signing request: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
raw := pem.EncodeToMemory(&pem.Block{
|
|
Type: pemfile.TypeX509CSR,
|
|
Bytes: der,
|
|
})
|
|
|
|
switch outputFile {
|
|
case "", "-":
|
|
os.Stdout.Write(raw)
|
|
|
|
default:
|
|
if err := os.WriteFile(outputFile, raw, 0600); err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
}
|