88 lines
1.7 KiB
Go
88 lines
1.7 KiB
Go
|
package ca
|
||
|
|
||
|
import (
|
||
|
"crypto/rsa"
|
||
|
"crypto/x509"
|
||
|
"encoding/pem"
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"time"
|
||
|
|
||
|
"github.com/spf13/cobra"
|
||
|
"src.lwithers.me.uk/go/rsa/pkg/ca"
|
||
|
"src.lwithers.me.uk/go/rsa/pkg/pemfile"
|
||
|
)
|
||
|
|
||
|
// Sign one or more CSRs.
|
||
|
func Sign(cmd *cobra.Command, args []string) {
|
||
|
csrFilename := args[0]
|
||
|
from, until := signingDates(365 * 24 * time.Hour)
|
||
|
|
||
|
// open the CA
|
||
|
ca, err := ca.Open(dir)
|
||
|
if err != nil {
|
||
|
fmt.Fprintln(os.Stderr, err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
|
||
|
// parse the CSR
|
||
|
csr, err := pemfile.ReadCSR(csrFilename)
|
||
|
if err != nil {
|
||
|
fmt.Fprintln(os.Stderr, err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
pubKey, ok := csr.PublicKey.(*rsa.PublicKey)
|
||
|
if !ok {
|
||
|
fmt.Fprintf(os.Stderr, "%s: public key is not RSA\n", csrFilename)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
|
||
|
// build the certificate template
|
||
|
var (
|
||
|
keyUsage x509.KeyUsage
|
||
|
extKeyUsage []x509.ExtKeyUsage
|
||
|
)
|
||
|
switch {
|
||
|
// TODO: CLI flags
|
||
|
case len(csr.DNSNames) == 0 && len(csr.IPAddresses) == 0:
|
||
|
extKeyUsage = append(extKeyUsage, x509.ExtKeyUsageClientAuth)
|
||
|
default:
|
||
|
extKeyUsage = append(extKeyUsage, x509.ExtKeyUsageServerAuth)
|
||
|
}
|
||
|
|
||
|
template := &x509.Certificate{
|
||
|
KeyUsage: keyUsage,
|
||
|
ExtKeyUsage: extKeyUsage,
|
||
|
Subject: csr.Subject,
|
||
|
NotBefore: from,
|
||
|
NotAfter: until,
|
||
|
DNSNames: csr.DNSNames,
|
||
|
IPAddresses: csr.IPAddresses,
|
||
|
}
|
||
|
|
||
|
// sign the certificate
|
||
|
cert, auditDir, err := ca.Sign(template, pubKey)
|
||
|
if err != nil {
|
||
|
fmt.Fprintln(os.Stderr, err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
raw := pem.EncodeToMemory(&pem.Block{
|
||
|
Type: pemfile.TypeX509Certificate,
|
||
|
Bytes: cert.Raw,
|
||
|
})
|
||
|
|
||
|
// TODO: copy CSR to audit dir
|
||
|
_ = auditDir
|
||
|
|
||
|
// write CSR to output file
|
||
|
switch outputFilename {
|
||
|
case "", "-":
|
||
|
os.Stdout.Write(raw)
|
||
|
default:
|
||
|
if err := os.WriteFile(outputFilename, raw, 0600); err != nil {
|
||
|
fmt.Fprintln(os.Stderr, err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
}
|
||
|
}
|