105 lines
2.4 KiB
Go
105 lines
2.4 KiB
Go
package hmpki
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"crypto/x509"
|
|
"crypto/x509/pkix"
|
|
"encoding/pem"
|
|
"path"
|
|
"time"
|
|
|
|
"git.handmadecities.com/HMC/shhh/pkg/pki"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
func init() {
|
|
generateCmd.AddCommand(generateClientCertCmd)
|
|
|
|
generateClientCertCmd.Flags().StringVar(
|
|
&CAFile,
|
|
"ca",
|
|
"",
|
|
"File for the CA that will sign the leaf",
|
|
)
|
|
generateClientCertCmd.MarkFlagRequired("ca")
|
|
generateClientCertCmd.MarkFlagFilename("ca")
|
|
|
|
generateClientCertCmd.Flags().StringVar(
|
|
&CAKeyFile,
|
|
"ca-key",
|
|
"",
|
|
"File for the CA private key that will sign the leaf",
|
|
)
|
|
generateClientCertCmd.MarkFlagRequired("ca-key")
|
|
generateClientCertCmd.MarkFlagFilename("ca-key")
|
|
|
|
generateClientCertCmd.Flags().StringVar(
|
|
&CommonName,
|
|
"common-name",
|
|
"",
|
|
"Common Name for the CA",
|
|
)
|
|
generateClientCertCmd.MarkFlagRequired("common-name")
|
|
}
|
|
|
|
var generateClientCertCmd = &cobra.Command{
|
|
Use: "client-cert",
|
|
Short: "Generate a leaf client certificate and private key",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
ca, err := pki.ParseCertFromFile(CAFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
caKey, err := pki.ParseKeyFromFile(CAKeyFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
certKey := pki.NewKey()
|
|
caTmpl := &x509.Certificate{
|
|
SerialNumber: pki.NewCertSerialNumber(),
|
|
Subject: pkix.Name{
|
|
CommonName: CommonName,
|
|
},
|
|
// Leaf certs valid for 1 year.
|
|
NotBefore: time.Now(),
|
|
NotAfter: time.Now().AddDate(1, 0, 0),
|
|
// This cert is a CA.
|
|
IsCA: false,
|
|
// Disambiguate `IsCA`
|
|
BasicConstraintsValid: true,
|
|
KeyUsage: x509.KeyUsageDigitalSignature,
|
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
|
}
|
|
|
|
caBytes, err := x509.CreateCertificate(
|
|
rand.Reader,
|
|
caTmpl,
|
|
// CA is the parent.
|
|
ca,
|
|
// The cert embeds its own public key.
|
|
&certKey.PublicKey,
|
|
// The CA's private key is the one signing the leaf cert.
|
|
caKey,
|
|
)
|
|
caPEMBytes := pem.EncodeToMemory(&pem.Block{
|
|
Type: pki.PEMTypeCertificate,
|
|
Bytes: caBytes,
|
|
})
|
|
|
|
// Write cert to disk.
|
|
cafn := path.Join(OutDir, Name+".crt")
|
|
err = createFileWith(cafn, caPEMBytes, pki.CertFilePerms)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// Write cert private key to disk.
|
|
keyfn := path.Join(OutDir, Name+".key")
|
|
err = createFileWith(keyfn, pki.MarshalKeyToPEM(caKey), pki.PrivateKeyFilePerms)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
},
|
|
}
|